diff options
Diffstat (limited to 'utils/test/testapi/opnfv_testapi')
10 files changed, 632 insertions, 65 deletions
diff --git a/utils/test/testapi/opnfv_testapi/common/raises.py b/utils/test/testapi/opnfv_testapi/common/raises.py index ec6b8a564..55c58c9e2 100644 --- a/utils/test/testapi/opnfv_testapi/common/raises.py +++ b/utils/test/testapi/opnfv_testapi/common/raises.py @@ -26,6 +26,10 @@ class Forbidden(Raiser): code = httplib.FORBIDDEN +class Conflict(Raiser): + code = httplib.CONFLICT + + class NotFound(Raiser): code = httplib.NOT_FOUND diff --git a/utils/test/testapi/opnfv_testapi/resources/handlers.py b/utils/test/testapi/opnfv_testapi/resources/handlers.py index 8a3a2db38..ed55c7028 100644 --- a/utils/test/testapi/opnfv_testapi/resources/handlers.py +++ b/utils/test/testapi/opnfv_testapi/resources/handlers.py @@ -50,7 +50,7 @@ class GenericApiHandler(web.RequestHandler): self.auth = self.settings["auth"] def prepare(self): - if self.request.method != "GET" and self.request.method != "DELETE": + if self.request.body: if self.request.headers.get("Content-Type") is not None: if self.request.headers["Content-Type"].startswith( DEFAULT_REPRESENTATION): @@ -106,20 +106,27 @@ class GenericApiHandler(web.RequestHandler): per_page = kwargs.get('per_page', 0) if query is None: query = {} + pipelines = list() + pipelines.append({'$match': query}) total_pages = 0 - if page > 0: - cursor = dbapi.db_list(self.table, query) - records_count = yield cursor.count() - total_pages = self._calc_total_pages(records_count, - last, - page, - per_page) - pipelines = self._set_pipelines(query, sort, last, page, per_page) - cursor = dbapi.db_aggregate(self.table, pipelines) data = list() - while (yield cursor.fetch_next): - data.append(self.format_data(cursor.next_object())) + cursor = dbapi.db_list(self.table, query) + records_count = yield cursor.count() + if records_count > 0: + if page > 0: + total_pages, return_nr = self._calc_total_pages(records_count, + last, + page, + per_page) + pipelines = self._set_pipelines(pipelines, + sort, + return_nr, + page, + per_page) + cursor = dbapi.db_aggregate(self.table, pipelines) + while (yield cursor.fetch_next): + data.append(self.format_data(cursor.next_object())) if res_op is None: res = {self.table: data} else: @@ -145,21 +152,17 @@ class GenericApiHandler(web.RequestHandler): if page > 1 and page > total_pages: raises.BadRequest( 'Request page > total_pages [{}]'.format(total_pages)) - return total_pages + return total_pages, records_nr @staticmethod - def _set_pipelines(query, sort, last, page, per_page): - pipelines = list() - if query: - pipelines.append({'$match': query}) + def _set_pipelines(pipelines, sort, return_nr, page, per_page): if sort: pipelines.append({'$sort': sort}) - if page > 0: - pipelines.append({'$skip': (page - 1) * per_page}) - pipelines.append({'$limit': per_page}) - elif last > 0: - pipelines.append({'$limit': last}) + over = (page - 1) * per_page + left = return_nr - over + pipelines.append({'$skip': over}) + pipelines.append({'$limit': per_page if per_page < left else left}) return pipelines @@ -186,6 +189,16 @@ class GenericApiHandler(web.RequestHandler): update_req['_id'] = str(data._id) self.finish_request(update_req) + @check.authenticate + @check.no_body + @check.not_exist + @check.updated_one_not_exist + def pure_update(self, data, query=None, **kwargs): + data = self.table_cls.from_dict(data) + update_req = self._update_requests(data) + yield dbapi.db_update(self.table, query, update_req) + self.finish_request() + def _update_requests(self, data): request = dict() for k, v in self.json_args.iteritems(): diff --git a/utils/test/testapi/opnfv_testapi/resources/models.py b/utils/test/testapi/opnfv_testapi/resources/models.py index e8fc532b7..6f04cc236 100644 --- a/utils/test/testapi/opnfv_testapi/resources/models.py +++ b/utils/test/testapi/opnfv_testapi/resources/models.py @@ -48,6 +48,29 @@ class ModelBase(object): return t + @classmethod + def from_dict_with_raise(cls, a_dict): + if a_dict is None: + return None + + attr_parser = cls.attr_parser() + t = cls() + for k, v in a_dict.iteritems(): + if k not in t.__dict__: + raise AttributeError( + '{} has no attribute {}'.format(cls.__name__, k)) + value = v + if isinstance(v, dict) and k in attr_parser: + value = attr_parser[k].from_dict(v) + elif isinstance(v, list) and k in attr_parser: + value = [] + for item in v: + value.append(attr_parser[k].from_dict(item)) + + t.__setattr__(k, value) + + return t + @staticmethod def attr_parser(): return {} diff --git a/utils/test/testapi/opnfv_testapi/resources/result_handlers.py b/utils/test/testapi/opnfv_testapi/resources/result_handlers.py index 2bf1792f2..9389d266d 100644 --- a/utils/test/testapi/opnfv_testapi/resources/result_handlers.py +++ b/utils/test/testapi/opnfv_testapi/resources/result_handlers.py @@ -155,7 +155,7 @@ class ResultsCLHandler(GenericResultHandler): @type last: L{string} @in last: query @required last: False - @param page: which page to list + @param page: which page to list, default to 1 @type page: L{int} @in page: query @required page: False @@ -180,7 +180,7 @@ class ResultsCLHandler(GenericResultHandler): return self.get_int('last', self.get_query_argument('last', 0)) def page_limit(): - return self.get_int('page', self.get_query_argument('page', 0)) + return self.get_int('page', self.get_query_argument('page', 1)) limitations = { 'sort': {'_id': descend_limit()}, diff --git a/utils/test/testapi/opnfv_testapi/resources/scenario_handlers.py b/utils/test/testapi/opnfv_testapi/resources/scenario_handlers.py index a89e7ee13..bd06400b4 100644 --- a/utils/test/testapi/opnfv_testapi/resources/scenario_handlers.py +++ b/utils/test/testapi/opnfv_testapi/resources/scenario_handlers.py @@ -1,5 +1,7 @@ import functools +from opnfv_testapi.common import message +from opnfv_testapi.common import raises from opnfv_testapi.resources import handlers import opnfv_testapi.resources.scenario_models as models from opnfv_testapi.tornado_swagger import swagger @@ -13,10 +15,10 @@ class GenericScenarioHandler(handlers.GenericApiHandler): self.table = self.db_scenarios self.table_cls = models.Scenario - def set_query(self, filters): + def set_query(self, locators): query = dict() elem_query = dict() - for k, v in filters.iteritems(): + for k, v in locators.iteritems(): if k == 'scenario': query['name'] = v elif k == 'installer': @@ -134,11 +136,19 @@ class ScenarioUpdater(object): self.version = version self.project = project - def update(self, item, op): + def update(self, item, action): updates = { - ('score', 'add'): self._update_requests_add_score, + ('scores', 'post'): self._update_requests_add_score, + ('trust_indicators', 'post'): self._update_requests_add_ti, + ('customs', 'post'): self._update_requests_add_customs, + ('customs', 'put'): self._update_requests_update_customs, + ('customs', 'delete'): self._update_requests_delete_customs, + ('projects', 'post'): self._update_requests_add_projects, + ('projects', 'put'): self._update_requests_update_projects, + ('projects', 'delete'): self._update_requests_delete_projects, + ('owner', 'put'): self._update_requests_change_owner, } - updates[(item, op)](self.data) + updates[(item, action)](self.data) return self.data.format() @@ -170,6 +180,83 @@ class ScenarioUpdater(object): project.scores.append( models.ScenarioScore.from_dict(self.body)) + @iter_installers + @iter_versions + @iter_projects + def _update_requests_add_ti(self, project): + project.trust_indicators.append( + models.ScenarioTI.from_dict(self.body)) + + @iter_installers + @iter_versions + @iter_projects + def _update_requests_add_customs(self, project): + project.customs = list(set(project.customs + self.body)) + + @iter_installers + @iter_versions + @iter_projects + def _update_requests_update_customs(self, project): + project.customs = list(set(self.body)) + + @iter_installers + @iter_versions + @iter_projects + def _update_requests_delete_customs(self, project): + project.customs = filter( + lambda f: f not in self.body, + project.customs) + + @iter_installers + @iter_versions + def _update_requests_add_projects(self, version): + exists = list() + malformat = list() + for n in self.body: + try: + f_n = models.ScenarioProject.from_dict_with_raise(n) + if not any(o.project == f_n.project for o in version.projects): + version.projects.append(f_n) + else: + exists.append(n['project']) + except Exception as e: + malformat.append(e.message) + if malformat: + raises.BadRequest(message.bad_format(malformat)) + elif exists: + raises.Conflict(message.exist('projects', exists)) + + @iter_installers + @iter_versions + def _update_requests_update_projects(self, version): + exists = list() + malformat = list() + projects = list() + for n in self.body: + try: + f_n = models.ScenarioProject.from_dict_with_raise(n) + if not any(o.project == f_n.project for o in projects): + projects.append(models.ScenarioProject.from_dict(n)) + else: + exists.append(n['project']) + except: + malformat.append(n) + if malformat: + raises.BadRequest(message.bad_format(malformat)) + elif exists: + raises.Forbidden(message.exist('projects', exists)) + version.projects = projects + + @iter_installers + @iter_versions + def _update_requests_delete_projects(self, version): + version.projects = self._remove_projects(version.projects) + + @iter_installers + @iter_versions + def _update_requests_change_owner(self, version): + version.owner = self.body + def _filter_installers(self, installers): return self._filter('installer', installers) @@ -179,13 +266,50 @@ class ScenarioUpdater(object): def _filter_projects(self, projects): return self._filter('project', projects) + def _remove_projects(self, projects): + return self._remove('project', projects) + def _filter(self, item, items): return filter( lambda f: getattr(f, item) == getattr(self, item), items) + def _remove(self, field, fields): + return filter( + lambda f: getattr(f, field) not in self.body, + fields) + -class ScenarioScoresHandler(GenericScenarioHandler): +class GenericScenarioUpdateHandler(GenericScenarioHandler): + def __init__(self, application, request, **kwargs): + super(GenericScenarioUpdateHandler, self).__init__(application, + request, + **kwargs) + self.installer = None + self.version = None + self.project = None + self.item = None + self.action = None + + def do_update(self, item, action, locators): + self.item = item + self.action = action + for k, v in locators.iteritems(): + if not v: + v = self.get_query_argument(k) + setattr(self, k, v) + locators[k] = v + self.pure_update(query=self.set_query(locators=locators)) + + def _update_requests(self, data): + return ScenarioUpdater(data, + self.json_args, + self.installer, + self.version, + self.project).update(self.item, self.action) + + +class ScenarioScoresHandler(GenericScenarioUpdateHandler): @swagger.operation(nickname="addScoreRecord") def post(self, scenario): """ @@ -210,24 +334,271 @@ class ScenarioScoresHandler(GenericScenarioHandler): @type project: L{string} @in project: query @required project: True - @rtype: L{Scenario} @return 200: score is created. @raise 404: scenario/installer/version/project not existed """ - self.installer = self.get_query_argument('installer') - self.version = self.get_query_argument('version') - self.project = self.get_query_argument('project') + self.do_update('scores', + 'post', + locators={'scenario': scenario, + 'installer': None, + 'version': None, + 'project': None}) - filters = {'scenario': scenario, - 'installer': self.installer, - 'version': self.version, - 'project': self.project} - db_keys = ['name'] - self._update(query=self.set_query(filters=filters), db_keys=db_keys) - def _update_requests(self, data): - return ScenarioUpdater(data, - self.json_args, - self.installer, - self.version, - self.project).update('score', 'add') +class ScenarioTIsHandler(GenericScenarioUpdateHandler): + @swagger.operation(nickname="addTrustIndicatorRecord") + def post(self, scenario): + """ + @description: add a new trust indicator record + @notes: add a new trust indicator record to a project + POST /api/v1/scenarios/<scenario_name>/trust_indicators? \ + installer=<installer_name>& \ + version=<version_name>& \ + project=<project_name> + @param body: trust indicator to be added + @type body: L{ScenarioTI} + @in body: body + @param installer: installer type + @type installer: L{string} + @in installer: query + @required installer: True + @param version: version + @type version: L{string} + @in version: query + @required version: True + @param project: project name + @type project: L{string} + @in project: query + @required project: True + @return 200: trust indicator is added. + @raise 404: scenario/installer/version/project not existed + """ + self.do_update('trust_indicators', + 'post', + locators={'scenario': scenario, + 'installer': None, + 'version': None, + 'project': None}) + + +class ScenarioCustomsHandler(GenericScenarioUpdateHandler): + @swagger.operation(nickname="addCustomizedTestCases") + def post(self, scenario): + """ + @description: add customized test cases + @notes: add several test cases to a project + POST /api/v1/scenarios/<scenario_name>/customs? \ + installer=<installer_name>& \ + version=<version_name>& \ + project=<project_name> + @param body: test cases to be added + @type body: C{list} of L{string} + @in body: body + @param installer: installer type + @type installer: L{string} + @in installer: query + @required installer: True + @param version: version + @type version: L{string} + @in version: query + @required version: True + @param project: project name + @type project: L{string} + @in project: query + @required project: True + @return 200: test cases are added. + @raise 404: scenario/installer/version/project not existed + """ + self.do_update('customs', + 'post', + locators={'scenario': scenario, + 'installer': None, + 'version': None, + 'project': None}) + + @swagger.operation(nickname="updateCustomizedTestCases") + def put(self, scenario): + """ + @description: update customized test cases + @notes: substitute all the customized test cases + PUT /api/v1/scenarios/<scenario_name>/customs? \ + installer=<installer_name>& \ + version=<version_name>& \ + project=<project_name> + @param body: new supported test cases + @type body: C{list} of L{string} + @in body: body + @param installer: installer type + @type installer: L{string} + @in installer: query + @required installer: True + @param version: version + @type version: L{string} + @in version: query + @required version: True + @param project: project name + @type project: L{string} + @in project: query + @required project: True + @return 200: substitute test cases success. + @raise 404: scenario/installer/version/project not existed + """ + self.do_update('customs', + 'put', + locators={'scenario': scenario, + 'installer': None, + 'version': None, + 'project': None}) + + @swagger.operation(nickname="deleteCustomizedTestCases") + def delete(self, scenario): + """ + @description: delete one or several customized test cases + @notes: delete one or some customized test cases + DELETE /api/v1/scenarios/<scenario_name>/customs? \ + installer=<installer_name>& \ + version=<version_name>& \ + project=<project_name> + @param body: test case(s) to be deleted + @type body: C{list} of L{string} + @in body: body + @param installer: installer type + @type installer: L{string} + @in installer: query + @required installer: True + @param version: version + @type version: L{string} + @in version: query + @required version: True + @param project: project name + @type project: L{string} + @in project: query + @required project: True + @return 200: delete test case(s) success. + @raise 404: scenario/installer/version/project not existed + """ + self.do_update('customs', + 'delete', + locators={'scenario': scenario, + 'installer': None, + 'version': None, + 'project': None}) + + +class ScenarioProjectsHandler(GenericScenarioUpdateHandler): + @swagger.operation(nickname="addProjectsUnderScenario") + def post(self, scenario): + """ + @description: add projects to scenario + @notes: add one or multiple projects + POST /api/v1/scenarios/<scenario_name>/projects? \ + installer=<installer_name>& \ + version=<version_name> + @param body: projects to be added + @type body: C{list} of L{ScenarioProject} + @in body: body + @param installer: installer type + @type installer: L{string} + @in installer: query + @required installer: True + @param version: version + @type version: L{string} + @in version: query + @required version: True + @return 200: projects are added. + @raise 400: bad schema + @raise 409: conflict, project already exists + @raise 404: scenario/installer/version not existed + """ + self.do_update('projects', + 'post', + locators={'scenario': scenario, + 'installer': None, + 'version': None}) + + @swagger.operation(nickname="updateScenarioProjects") + def put(self, scenario): + """ + @description: replace all projects + @notes: substitute all projects, delete existed ones with new provides + PUT /api/v1/scenarios/<scenario_name>/projects? \ + installer=<installer_name>& \ + version=<version_name> + @param body: new projects + @type body: C{list} of L{ScenarioProject} + @in body: body + @param installer: installer type + @type installer: L{string} + @in installer: query + @required installer: True + @param version: version + @type version: L{string} + @in version: query + @required version: True + @return 200: replace projects success. + @raise 400: bad schema + @raise 404: scenario/installer/version not existed + """ + self.do_update('projects', + 'put', + locators={'scenario': scenario, + 'installer': None, + 'version': None}) + + @swagger.operation(nickname="deleteProjectsUnderScenario") + def delete(self, scenario): + """ + @description: delete one or multiple projects + @notes: delete one or multiple projects + DELETE /api/v1/scenarios/<scenario_name>/projects? \ + installer=<installer_name>& \ + version=<version_name> + @param body: projects(names) to be deleted + @type body: C{list} of L{string} + @in body: body + @param installer: installer type + @type installer: L{string} + @in installer: query + @required installer: True + @param version: version + @type version: L{string} + @in version: query + @required version: True + @return 200: delete project(s) success. + @raise 404: scenario/installer/version not existed + """ + self.do_update('projects', + 'delete', + locators={'scenario': scenario, + 'installer': None, + 'version': None}) + + +class ScenarioOwnerHandler(GenericScenarioUpdateHandler): + @swagger.operation(nickname="changeScenarioOwner") + def put(self, scenario): + """ + @description: change scenario owner + @notes: substitute all projects, delete existed ones with new provides + PUT /api/v1/scenarios/<scenario_name>/owner? \ + installer=<installer_name>& \ + version=<version_name> + @param body: new owner + @type body: L{string} + @in body: body + @param installer: installer type + @type installer: L{string} + @in installer: query + @required installer: True + @param version: version + @type version: L{string} + @in version: query + @required version: True + @return 200: change owner success. + @raise 404: scenario/installer/version not existed + """ + self.do_update('owner', + 'put', + locators={'scenario': scenario, + 'installer': None, + 'version': None}) diff --git a/utils/test/testapi/opnfv_testapi/resources/scenario_models.py b/utils/test/testapi/opnfv_testapi/resources/scenario_models.py index 9f5a07434..7d0770759 100644 --- a/utils/test/testapi/opnfv_testapi/resources/scenario_models.py +++ b/utils/test/testapi/opnfv_testapi/resources/scenario_models.py @@ -74,7 +74,8 @@ class ScenarioVersion(models.ModelBase): @property projects: @ptype projects: C{list} of L{ScenarioProject} """ - def __init__(self, version=None, projects=None): + def __init__(self, owner=None, version=None, projects=None): + self.owner = owner self.version = version self.projects = list_default(projects) @@ -83,7 +84,9 @@ class ScenarioVersion(models.ModelBase): return {'projects': ScenarioProject} def __eq__(self, other): - return [self.version == other.version and self._projects_eq(other)] + return [self.version == other.version and + self.owner == other.owner and + self._projects_eq(other)] def __ne__(self, other): return not self.__eq__(other) diff --git a/utils/test/testapi/opnfv_testapi/router/url_mappings.py b/utils/test/testapi/opnfv_testapi/router/url_mappings.py index 4f990f03e..9c9556c6b 100644 --- a/utils/test/testapi/opnfv_testapi/router/url_mappings.py +++ b/utils/test/testapi/opnfv_testapi/router/url_mappings.py @@ -56,6 +56,14 @@ mappings = [ (r"/api/v1/scenarios/([^/]+)", scenario_handlers.ScenarioGURHandler), (r"/api/v1/scenarios/([^/]+)/scores", scenario_handlers.ScenarioScoresHandler), + (r"/api/v1/scenarios/([^/]+)/trust_indicators", + scenario_handlers.ScenarioTIsHandler), + (r"/api/v1/scenarios/([^/]+)/customs", + scenario_handlers.ScenarioCustomsHandler), + (r"/api/v1/scenarios/([^/]+)/projects", + scenario_handlers.ScenarioProjectsHandler), + (r"/api/v1/scenarios/([^/]+)/owner", + scenario_handlers.ScenarioOwnerHandler), # static path (r'/(.*\.(css|png|gif|js|html|json|map|woff2|woff|ttf))', diff --git a/utils/test/testapi/opnfv_testapi/tests/unit/resources/test_base.py b/utils/test/testapi/opnfv_testapi/tests/unit/resources/test_base.py index aa6b83544..77a8d18c1 100644 --- a/utils/test/testapi/opnfv_testapi/tests/unit/resources/test_base.py +++ b/utils/test/testapi/opnfv_testapi/tests/unit/resources/test_base.py @@ -92,21 +92,35 @@ class TestBase(testing.AsyncHTTPTestCase): headers=self.headers) return self._get_return(res, self.list_res) - def update(self, new=None, *args): - if new: + def update_direct_url(self, url, new=None): + if new and hasattr(new, 'format'): new = new.format() - res = self.fetch(self._get_uri(*args), + res = self.fetch(url, method='PUT', body=json.dumps(new), headers=self.headers) return self._get_return(res, self.update_res) - def delete(self, *args): - res = self.fetch(self._get_uri(*args), - method='DELETE', - headers=self.headers) + def update(self, new=None, *args): + return self.update_direct_url(self._get_uri(*args), new) + + def delete_direct_url(self, url, body): + if body: + res = self.fetch(url, + method='DELETE', + body=json.dumps(body), + headers=self.headers, + allow_nonstandard_methods=True) + else: + res = self.fetch(url, + method='DELETE', + headers=self.headers) + return res.code, res.body + def delete(self, *args): + return self.delete_direct_url(self._get_uri(*args), None) + @staticmethod def _get_valid_args(*args): new_args = tuple(['%s' % arg for arg in args if arg is not None]) @@ -132,7 +146,10 @@ class TestBase(testing.AsyncHTTPTestCase): def _get_return(self, res, cls): code = res.code body = res.body - return code, self._get_return_body(code, body, cls) + if body: + return code, self._get_return_body(code, body, cls) + else: + return code, None @staticmethod def _get_return_body(code, body, cls): diff --git a/utils/test/testapi/opnfv_testapi/tests/unit/resources/test_scenario.py b/utils/test/testapi/opnfv_testapi/tests/unit/resources/test_scenario.py index c12c52ba9..466caaf13 100644 --- a/utils/test/testapi/opnfv_testapi/tests/unit/resources/test_scenario.py +++ b/utils/test/testapi/opnfv_testapi/tests/unit/resources/test_scenario.py @@ -168,15 +168,30 @@ class TestScenarioUpdate(TestScenarioBase): self.version, 'functest') + def update_url_fixture(item): + def _update_url_fixture(xstep): + def wrapper(self, *args, **kwargs): + locator = None + if item in ['projects', 'owner']: + locator = 'installer={}&version={}'.format( + self.installer, + self.version) + self.update_url = '{}/{}?{}'.format(self.scenario_url, + item, + locator) + xstep(self, *args, **kwargs) + return wrapper + return _update_url_fixture + def update_partial(operate, expected): - def _update(set_update): + def _update_partial(set_update): @functools.wraps(set_update) - def wrap(self): + def wrapper(self): update, scenario = set_update(self, deepcopy(self.req_d)) code, body = getattr(self, operate)(update, self.scenario) getattr(self, expected)(code, scenario) - return wrap - return _update + return wrapper + return _update_partial @update_partial('_add', '_success') def test_addScore(self, scenario): @@ -189,9 +204,112 @@ class TestScenarioUpdate(TestScenarioBase): return add, scenario + @update_partial('_add', '_success') + def test_addTrustIndicator(self, scenario): + add = models.ScenarioTI(date=str(datetime.now()), status='gold') + projects = scenario['installers'][0]['versions'][0]['projects'] + functest = filter(lambda f: f['project'] == 'functest', projects)[0] + functest['trust_indicators'].append(add.format()) + self.update_url = '{}/trust_indicators?{}'.format(self.scenario_url, + self.locate_project) + + return add, scenario + + @update_partial('_add', '_success') + def test_addCustoms(self, scenario): + add = ['odl', 'parser', 'vping_ssh'] + projects = scenario['installers'][0]['versions'][0]['projects'] + functest = filter(lambda f: f['project'] == 'functest', projects)[0] + functest['customs'] = list(set(functest['customs'] + add)) + self.update_url = '{}/customs?{}'.format(self.scenario_url, + self.locate_project) + return add, scenario + + @update_partial('_update', '_success') + def test_updateCustoms(self, scenario): + news = ['odl', 'parser', 'vping_ssh'] + projects = scenario['installers'][0]['versions'][0]['projects'] + functest = filter(lambda f: f['project'] == 'functest', projects)[0] + functest['customs'] = news + self.update_url = '{}/customs?{}'.format(self.scenario_url, + self.locate_project) + + return news, scenario + + @update_partial('_delete', '_success') + def test_deleteCustoms(self, scenario): + obsoletes = ['vping_ssh'] + projects = scenario['installers'][0]['versions'][0]['projects'] + functest = filter(lambda f: f['project'] == 'functest', projects)[0] + functest['customs'] = ['healthcheck'] + self.update_url = '{}/customs?{}'.format(self.scenario_url, + self.locate_project) + + return obsoletes, scenario + + @update_url_fixture('projects') + @update_partial('_add', '_success') + def test_addProjects_succ(self, scenario): + add = models.ScenarioProject(project='qtip').format() + scenario['installers'][0]['versions'][0]['projects'].append(add) + return [add], scenario + + @update_url_fixture('projects') + @update_partial('_add', '_conflict') + def test_addProjects_already_exist(self, scenario): + add = models.ScenarioProject(project='functest').format() + scenario['installers'][0]['versions'][0]['projects'].append(add) + return [add], scenario + + @update_url_fixture('projects') + @update_partial('_add', '_bad_request') + def test_addProjects_bad_schema(self, scenario): + add = models.ScenarioProject(project='functest').format() + add['score'] = None + scenario['installers'][0]['versions'][0]['projects'].append(add) + return [add], scenario + + @update_url_fixture('projects') + @update_partial('_update', '_success') + def test_updateProjects_succ(self, scenario): + update = models.ScenarioProject(project='qtip').format() + scenario['installers'][0]['versions'][0]['projects'] = [update] + return [update], scenario + + @update_url_fixture('projects') + @update_partial('_update', '_bad_request') + def test_updateProjects_bad_schema(self, scenario): + update = models.ScenarioProject(project='functest').format() + update['score'] = None + scenario['installers'][0]['versions'][0]['projects'] = [update] + return [update], scenario + + @update_url_fixture('projects') + @update_partial('_delete', '_success') + def test_deleteProjects(self, scenario): + deletes = ['functest'] + projects = scenario['installers'][0]['versions'][0]['projects'] + scenario['installers'][0]['versions'][0]['projects'] = filter( + lambda f: f['project'] != 'functest', + projects) + return deletes, scenario + + @update_url_fixture('owner') + @update_partial('_update', '_success') + def test_changeOwner(self, scenario): + new_owner = 'new_owner' + scenario['installers'][0]['versions'][0]['owner'] = 'www' + return new_owner, scenario + def _add(self, update_req, new_scenario): return self.post_direct_url(self.update_url, update_req) + def _update(self, update_req, new_scenario): + return self.update_direct_url(self.update_url, update_req) + + def _delete(self, update_req, new_scenario): + return self.delete_direct_url(self.update_url, update_req) + def _success(self, status, new_scenario): self.assertEqual(status, httplib.OK) self._get_and_assert(new_scenario.get('name'), new_scenario) @@ -201,3 +319,6 @@ class TestScenarioUpdate(TestScenarioBase): def _bad_request(self, status, new_scenario): self.assertEqual(status, httplib.BAD_REQUEST) + + def _conflict(self, status, new_scenario): + self.assertEqual(status, httplib.CONFLICT) diff --git a/utils/test/testapi/opnfv_testapi/tornado_swagger/swagger.py b/utils/test/testapi/opnfv_testapi/tornado_swagger/swagger.py index 83f389a6b..6125c9554 100644 --- a/utils/test/testapi/opnfv_testapi/tornado_swagger/swagger.py +++ b/utils/test/testapi/opnfv_testapi/tornado_swagger/swagger.py @@ -94,11 +94,18 @@ class DocParser(object): def _parse_type(self, **kwargs): arg = kwargs.get('arg', None) - body = self._get_body(**kwargs) - self.params.setdefault(arg, {}).update({ - 'name': arg, - 'dataType': body - }) + code = self._parse_epytext_para('code', **kwargs) + link = self._parse_epytext_para('link', **kwargs) + if code is None: + self.params.setdefault(arg, {}).update({ + 'name': arg, + 'type': link + }) + elif code == 'list': + self.params.setdefault(arg, {}).update({ + 'type': 'array', + 'items': {'type': link} + }) def _parse_in(self, **kwargs): arg = kwargs.get('arg', None) |