Create UTs for newton.pubs module 37/14337/2
authorVictor Morales <victor.morales@intel.com>
Thu, 21 Sep 2017 18:46:58 +0000 (11:46 -0700)
committerVictor Morales <victor.morales@intel.com>
Fri, 22 Sep 2017 00:13:04 +0000 (17:13 -0700)
This commit creates Unit Tests for covering function defined in
newton/pubs folder. It also makes a refactoring of the functions
cleaning unused code.

Change-Id: I5931871a1bbb3732b7c68cc8a245899283b6fd99
Signed-off-by: Victor Morales <victor.morales@intel.com>
Issue-Id: MULTICLOUD-83

newton/newton/pub/msapi/extsys.py
newton/newton/pub/tests/__init__.py [new file with mode: 0644]
newton/newton/pub/tests/test_extsys.py [new file with mode: 0644]
newton/newton/pub/tests/test_restcall.py [new file with mode: 0644]
newton/newton/pub/utils/restcall.py

index 7606699..aa6a159 100644 (file)
@@ -13,9 +13,8 @@ import json
 import logging
 import re
 
-from rest_framework import status
 from newton.pub.exceptions import VimDriverNewtonException
-from newton.pub.utils.restcall import req_by_msb,req_to_aai
+from newton.pub.utils import restcall
 
 
 logger = logging.getLogger(__name__)
@@ -26,7 +25,7 @@ def get_vim_by_id(vim_id):
 
     if cloud_owner and cloud_region_id:
         retcode, content, status_code = \
-            req_to_aai("/cloud-infrastructure/cloud-regions/cloud-region/%s/%s"
+            restcall.req_to_aai("/cloud-infrastructure/cloud-regions/cloud-region/%s/%s"
                        % (cloud_owner,cloud_region_id),"GET")
         if retcode != 0:
             logger.error("Status code is %s, detail is %s.", status_code, content)
@@ -37,10 +36,9 @@ def get_vim_by_id(vim_id):
 
         #assume esr-system-info-id is composed by {cloud-owner} _ {cloud-region-id}
         retcode2,content2,status_code2 = \
-            req_to_aai("/cloud-infrastructure/cloud-regions/cloud-region/%s/%s"
-                       + "/esr-system-info-list/esr-system-info/%s_%s" \
-                       % (cloud_owner,cloud_region_id,cloud_owner,cloud_region_id),
-                       "GET")
+            restcall.req_to_aai(("/cloud-infrastructure/cloud-regions/cloud-region/%(owner)s/%(region)s"
+                                 "/esr-system-info-list/esr-system-info/%(owner)s_%(region)s" % {
+                "owner": cloud_owner, "region": cloud_region_id}), "GET")
         if retcode2 != 0:
             logger.error("Status code is %s, detail is %s.", status_code, content)
             raise VimDriverNewtonException(
@@ -49,8 +47,7 @@ def get_vim_by_id(vim_id):
         tmp_authinfo = json.JSONDecoder().decode(content2)
 
         #convert vim information
-
-        if tmp_viminfo:
+        if tmp_viminfo and tmp_authinfo:
             viminfo = {}
             viminfo['vimId'] = vim_id
             viminfo['cloud_owner'] = cloud_owner
@@ -61,28 +58,22 @@ def get_vim_by_id(vim_id):
             viminfo['cloud_extra_info'] = tmp_viminfo['cloud-extra-info']
             viminfo['cloud_epa_caps'] = tmp_viminfo['cloud-epa-caps']
 
-            if tmp_authinfo:
-                viminfo['userName'] = tmp_authinfo['user-name']
-                viminfo['password'] = tmp_authinfo['password']
-                viminfo['domain'] = tmp_authinfo['cloud-domain']
-                viminfo['url'] = tmp_authinfo['service-url']
-                viminfo['tenant'] = tmp_authinfo['default-tenant']
-                viminfo['cacert'] = tmp_authinfo['ssl-cacert']
-                viminfo['insecure'] = tmp_authinfo['ssl-insecure']
-            else:
-                return None
+            viminfo['userName'] = tmp_authinfo['user-name']
+            viminfo['password'] = tmp_authinfo['password']
+            viminfo['domain'] = tmp_authinfo['cloud-domain']
+            viminfo['url'] = tmp_authinfo['service-url']
+            viminfo['tenant'] = tmp_authinfo['default-tenant']
+            viminfo['cacert'] = tmp_authinfo['ssl-cacert']
+            viminfo['insecure'] = tmp_authinfo['ssl-insecure']
 
             return viminfo
-        else:
-            return None
-    else:
-        return None
+    return None
 
 def delete_vim_by_id(vim_id):
     cloud_owner, cloud_region_id = decode_vim_id(vim_id)
     if cloud_owner and cloud_region_id:
         retcode, content, status_code = \
-            req_to_aai("/cloud-infrastructure/cloud-regions/cloud-region/%s/%s"
+            restcall.req_to_aai("/cloud-infrastructure/cloud-regions/cloud-region/%s/%s"
                        % ( cloud_owner, cloud_region_id), "DELETE")
         if retcode != 0:
             logger.error("Status code is %s, detail is %s.", status_code, content)
diff --git a/newton/newton/pub/tests/__init__.py b/newton/newton/pub/tests/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/newton/newton/pub/tests/test_extsys.py b/newton/newton/pub/tests/test_extsys.py
new file mode 100644 (file)
index 0000000..5ddbbcb
--- /dev/null
@@ -0,0 +1,111 @@
+# Copyright (c) 2017 Intel Corporation.
+#
+# 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.
+
+import json
+
+import mock
+import six
+import unittest
+
+from newton.pub.exceptions import VimDriverNewtonException
+from newton.pub.msapi import extsys
+from newton.pub.utils import restcall
+
+MOCK_VIM_INFO = {
+    "cloud-type": "openstack",
+    "complex-name": "complex",
+    "cloud-region-version": "Regionv1",
+    "cloud-extra-info": "type",
+    "cloud-epa-caps": "epa"
+}
+
+MOCK_ESR_SYSTEM_INFO = {
+    "user-name": "test",
+    "password": "secret",
+    "cloud-domain": "default",
+    "service-url": "http://localhost",
+    "default-tenant": "demo",
+    "ssl-cacert": None,
+    "ssl-insecure": None
+}
+
+
+def returnList(items):
+    def func():
+        for item in items:
+            yield item
+        yield mock.DEFAULT
+
+    generator = func()
+
+    def effect(*args, **kwargs):
+        return six.next(generator)
+
+    return effect
+
+
+class TestEpaCaps(unittest.TestCase):
+    cloud_onwer = "windriver-hudson-cd"
+    cloud_region_id = "RegionOne"
+    vim_id = cloud_onwer + "_" + cloud_region_id
+
+    def setUp(self):
+        self.req_to_aai_backup = restcall.req_to_aai
+
+    def tearDown(self):
+        restcall.req_to_aai = self.req_to_aai_backup
+
+    def test_get_vim_by_id(self):
+        values = [
+            (1, "test_content", 500), # Failure first call
+            (0, json.dumps(MOCK_VIM_INFO), None), (1, "test_content", 500), # Failure second call
+            (0, json.dumps(MOCK_VIM_INFO), None), (0, json.dumps(MOCK_ESR_SYSTEM_INFO), None)  # Success calls
+        ]
+
+        restcall.req_to_aai = mock.Mock(side_effect=returnList(values))
+        self.assertRaises(VimDriverNewtonException, extsys.get_vim_by_id, self.vim_id)
+        restcall.req_to_aai.assert_called_once()
+
+        self.assertRaises(VimDriverNewtonException, extsys.get_vim_by_id, self.vim_id)
+
+        viminfo = extsys.get_vim_by_id(self.vim_id)
+        self.assertIsNotNone(viminfo)
+        self.assertEquals(self.vim_id, viminfo['vimId'])
+        self.assertEquals(self.cloud_onwer, viminfo['cloud_owner'])
+        self.assertEquals(self.cloud_region_id, viminfo['cloud_region_id'])
+        self.assertEquals(MOCK_VIM_INFO['cloud-type'], viminfo['type'])
+        self.assertEquals(MOCK_VIM_INFO['complex-name'], viminfo['name'])
+        self.assertEquals(MOCK_VIM_INFO['cloud-region-version'], viminfo['version'])
+        self.assertEquals(MOCK_VIM_INFO['cloud-extra-info'], viminfo['cloud_extra_info'])
+        self.assertEquals(MOCK_VIM_INFO['cloud-epa-caps'], viminfo['cloud_epa_caps'])
+
+        self.assertEquals(MOCK_ESR_SYSTEM_INFO['user-name'], viminfo['userName'])
+        self.assertEquals(MOCK_ESR_SYSTEM_INFO['password'], viminfo['password'])
+        self.assertEquals(MOCK_ESR_SYSTEM_INFO['cloud-domain'], viminfo['domain'])
+        self.assertEquals(MOCK_ESR_SYSTEM_INFO['service-url'], viminfo['url'])
+        self.assertEquals(MOCK_ESR_SYSTEM_INFO['default-tenant'], viminfo['tenant'])
+        self.assertEquals(MOCK_ESR_SYSTEM_INFO['ssl-cacert'], viminfo['cacert'])
+        self.assertEquals(MOCK_ESR_SYSTEM_INFO['ssl-insecure'], viminfo['insecure'])
+
+    def test_delete_vim_by_id(self):
+        values = [(1, "test_content", 500),(0, None, None)]
+
+        restcall.req_to_aai = mock.Mock(side_effect=returnList(values))
+        self.assertRaises(VimDriverNewtonException, extsys.delete_vim_by_id, self.vim_id)
+        self.assertEquals(0, extsys.delete_vim_by_id(self.vim_id))
+
+    def test_decode_vim_id_successfuly(self):
+        owner, region_id = extsys.decode_vim_id(self.vim_id)
+        self.assertEquals(self.cloud_onwer, owner)
+        self.assertEquals(self.cloud_region_id, region_id)
\ No newline at end of file
diff --git a/newton/newton/pub/tests/test_restcall.py b/newton/newton/pub/tests/test_restcall.py
new file mode 100644 (file)
index 0000000..28def73
--- /dev/null
@@ -0,0 +1,110 @@
+# Copyright (c) 2017 Intel Corporation.
+#
+# 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.
+
+from httplib2 import Http
+import mock
+from rest_framework import status
+import unittest
+
+from newton.pub.utils import restcall
+
+
+class TestRestCall(unittest.TestCase):
+    base_url = "http://localhost"
+    resource = "compute"
+
+    @mock.patch.object(Http, 'request')
+    def test_unknown_failure_call_req(self, mock_http):
+        mock_http.raiseError.side_effect = mock.Mock(
+            side_effect=Exception('Test'))
+        args = [
+            self.base_url, "user", "password", "auth_type",
+            self.resource, "get", {"extra": "test"}
+        ]
+
+        ret = restcall._call_req(*args)
+        self.assertEquals(3, ret[0])
+        self.assertEquals(status.HTTP_500_INTERNAL_SERVER_ERROR, ret[2])
+
+
+    @mock.patch.object(Http, 'request')
+    def test_invalid_output_call_req(self, mock_http):
+        args = [
+            self.base_url, "user", "password", "auth_type",
+            self.resource, "get", {"extra": "test"}
+        ]
+
+        mock_http.return_value = ({'status': None},
+                                  str.encode("test", 'utf-8'))
+
+        ret = restcall._call_req(*args)
+        self.assertEquals(1, ret[0])
+        self.assertEquals("test", ret[1])
+        self.assertIsNone(ret[2])
+
+    @mock.patch.object(Http, 'request')
+    def test_req_by_msb(self, mock_http):
+        resp_body = "test_body"
+        resp_status=status.HTTP_200_OK
+        mock_http.return_value = (
+            {'status': resp_status},
+            str.encode(resp_body, 'utf-8'))
+
+
+        ret = restcall.req_by_msb(self.resource, "delete")
+        self.assertEquals(0, ret[0])
+        self.assertEquals(resp_body, ret[1])
+        self.assertEquals(resp_status, ret[2])
+
+    @mock.patch.object(Http, 'request')
+    def test_req_to_vim(self, mock_http):
+        resp_body = "test_body"
+        resp_status=status.HTTP_200_OK
+        mock_http.return_value = (
+            {'status': resp_status},
+            str.encode(resp_body, 'utf-8'))
+
+        ret = restcall.req_to_vim(self.base_url, self.resource, "get")
+        self.assertEquals(0, ret[0])
+        self.assertEquals(resp_body, ret[1])
+        self.assertEquals(resp_status, ret[2])
+
+    @mock.patch.object(Http, 'request')
+    def test_req_to_aai(self, mock_http):
+        resp_body = "test_body"
+        resp_status=status.HTTP_200_OK
+        mock_http.return_value = (
+            {'status': resp_status},
+            str.encode(resp_body, 'utf-8'))
+
+        ret = restcall.req_to_aai(self.resource, "post")
+        self.assertEquals(0, ret[0])
+        self.assertEquals(resp_body, ret[1])
+        self.assertEquals(resp_status, ret[2])
+
+    def test_combine_url(self):
+        self.assertEquals(self.base_url,
+                          restcall._combine_url(self.base_url, ""))
+        self.assertEquals(self.base_url + "/" + self.resource,
+                          restcall._combine_url(self.base_url + "/",
+                                               "/" + self.resource))
+        self.assertEquals(self.base_url + "/" + self.resource,
+                          restcall._combine_url(self.base_url + "/",
+                                               self.resource))
+        self.assertEquals(self.base_url + "/" + self.resource,
+                          restcall._combine_url(self.base_url,
+                                               "/" + self.resource))
+        self.assertEquals(self.base_url + "/" + self.resource,
+                          restcall._combine_url(self.base_url,
+                                               self.resource))
index a283868..6444014 100644 (file)
@@ -9,13 +9,13 @@
 # distributed under the License is distributed on an "AS IS" BASIS,
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
-import sys
+import codecs
 import json
 import traceback
+import sys
+
 import logging
 from six.moves import urllib
-import uuid
-from six.moves import http_client
 import httplib2
 import uuid
 
@@ -32,15 +32,13 @@ MAX_RETRY_TIME = 3
 logger = logging.getLogger(__name__)
 
 
-def call_req(base_url, user, passwd, auth_type,
+def _call_req(base_url, user, passwd, auth_type,
              resource, method, extra_headers='', content=''):
     callid = str(uuid.uuid1())
-#    logger.debug("[%s]call_req('%s','%s','%s',%s,'%s','%s','%s')" % (
-#        callid, base_url, user, passwd, auth_type, resource, method, content))
     ret = None
     resp_status = None
     try:
-        full_url = combine_url(base_url, resource)
+        full_url = _combine_url(base_url, resource)
         headers = {
             'content-type': 'application/json',
             'accept': 'application/json'
@@ -50,7 +48,8 @@ def call_req(base_url, user, passwd, auth_type,
             headers.update(extra_headers)
         if user:
             headers['Authorization'] = \
-                'Basic ' + ('%s:%s' % (user, passwd)).encode("base64")
+                'Basic ' + str(codecs.encode('%s:%s' % (user, passwd), "ascii"))
+
         ca_certs = None
         for retry_times in range(MAX_RETRY_TIME):
             http = httplib2.Http(
@@ -63,9 +62,8 @@ def call_req(base_url, user, passwd, auth_type,
                                                   body=content,
                                                   headers=headers)
                 resp_status, resp_body = \
-                    resp['status'], resp_content.decode('UTF-8')
-#                logger.debug("[%s][%d]status=%s,resp_body=%s)" %
-#                             (callid, retry_times, resp_status, resp_body))
+                    resp['status'], codecs.decode(
+                        resp_content, 'UTF-8')
                 if resp_status in status_ok_list:
                     ret = [0, resp_body, resp_status]
                 else:
@@ -80,7 +78,7 @@ def call_req(base_url, user, passwd, auth_type,
                 raise ex
     except urllib.error.URLError as err:
         ret = [2, str(err), resp_status]
-    except Exception as ex:
+    except Exception:
         logger.error(traceback.format_exc())
         logger.error("[%s]ret=%s" % (callid, str(sys.exc_info())))
         if not resp_status:
@@ -89,22 +87,20 @@ def call_req(base_url, user, passwd, auth_type,
     except:
         logger.error(traceback.format_exc())
         ret = [4, str(sys.exc_info()), resp_status]
-
-#    logger.debug("[%s]ret=%s" % (callid, str(ret)))
     return ret
 
 
 def req_by_msb(resource, method, content=''):
     base_url = "http://%s:%s/" % (config.MSB_SERVICE_ADDR, config.MSB_SERVICE_PORT)
-#    logger.debug("requests--get::> %s" % "33")
-    return call_req(base_url, "", "", rest_no_auth,
+    return _call_req(base_url, "", "", rest_no_auth,
                     resource, method, "", content)
 
 
 def req_to_vim(base_url, resource, method, extra_headers='', content=''):
-    return call_req(base_url, "", "", rest_no_auth,
+    return _call_req(base_url, "", "", rest_no_auth,
                     resource, method, extra_headers, content)
 
+
 def req_to_aai(resource, method, content='', appid=config.MULTICLOUD_APP_ID):
     tmp_trasaction_id = str(uuid.uuid1())
     headers = {
@@ -115,11 +111,11 @@ def req_to_aai(resource, method, content='', appid=config.MULTICLOUD_APP_ID):
     }
 
     logger.debug("req_to_aai--%s::> %s, %s" % (tmp_trasaction_id, method, resource))
-    return call_req(config.AAI_BASE_URL, config.AAI_USERNAME, config.AAI_PASSWORD, rest_no_auth,
+    return _call_req(config.AAI_BASE_URL, config.AAI_USERNAME, config.AAI_PASSWORD, rest_no_auth,
                     resource, method, content=json.dumps(content), extra_headers=headers)
 
 
-def combine_url(base_url, resource):
+def _combine_url(base_url, resource):
     full_url = None
 
     if not resource: