def test_users_delete(self): """ register a username, get an auth token, delete user again idea: register second user to check """ app = TestApp(main({})) _name = "mary" res = app.put("/users", _name, status=200) self.assertTrue("application/json; charset=UTF-8" in res.headers["Content-Type"]) # store the body as json _json = json.loads(res.body) # print(_json['token']) self.assertTrue("0.1dev" in _json["api-version"]) self.assertTrue(_name in str(_json["token"])) _token = _json["token"] # print("the token from res: " + _token) # try using an invalid token: get coverage for the valid_token function _invalid_token = _token.replace("-", "") # removing the '-' # print("_invalid_token: " + _invalid_token) _auth_header = {"X-Messaging-Token": str(_invalid_token)} # calling with the invalid_token we expect 401: Unauthorized res2 = app.delete_json("/users", params=_name, headers=_auth_header, status=401) _auth_header = {"X-Messaging-Token": str(_token)} # now we have a token and can authenticate... and delete the user # delete the user # res2 = app.delete('/users', params=_name, res2 = app.delete_json("/users", params=_name, headers=_auth_header, status=200) # print(res2) self.assertTrue("goodbye" in json.loads(res2.body).keys()) self.assertTrue(_name in json.loads(res2.body).values())
class ApplicationTestMixin(object): def setUp(self): super(ApplicationTestMixin, self).setUp() self.config = {"db": {"url": "sqlite://"}} self.great = create_app(config=self.config) self.app = TestApp(wsgi.create_app(self.great)) METADATA.create_all(self.great.bin.provide("engine").connect()) def create(self, **params): return self.app.post_json(self.url.to_text(), params=params).json def delete(self, **params): return self.app.delete_json(self.url.to_text(), params=params) def list(self, **params): return self.app.get(self.url.to_text(), params=params).json def tracked(self, **params): return self.app.get( self.url.child(u"tracked").to_text(), params=params, ).json def test_invalid_json(self): self.app.post(self.url.to_text(), params="", status=400) def test_unknown_method(self): self.app.request(self.url.to_text(), method=b"TRACE", status=405)
def _test_request(self, swagger_plugin=None, method='GET', url='/thing', route_url=None, request_json=VALID_JSON, response_json=VALID_JSON, headers=None, content_type='application/json', extra_check=lambda *args, **kwargs: True): if swagger_plugin is None: swagger_plugin = self._make_swagger_plugin() if response_json is None: response_json = {} if route_url is None: route_url = url bottle_app = Bottle() bottle_app.install(swagger_plugin) @bottle_app.route(route_url, method) def do_thing(*args, **kwargs): extra_check(*args, **kwargs) return response_json() if hasattr(response_json, "__call__") else response_json test_app = TestApp(bottle_app) if method.upper() == 'GET': response = test_app.get(url, expect_errors=True, headers=headers) elif method.upper() == 'POST': if content_type == 'application/json': response = test_app.post_json(url, request_json, expect_errors=True, headers=headers) else: response = test_app.post(url, request_json, content_type=content_type, expect_errors=True, headers=headers) elif method.upper() == 'DELETE': if content_type == 'aplication/json': response = test_app.delete_json(url, request_json, expect_errors=True, headers=headers) else: response = test_app.delete(url, request_json, content_type=content_type, expect_errors=True, headers=headers) else: raise Exception("Invalid method {}".format(method)) return response
def test_users_delete(self): """ register a username, get an auth token, delete user again idea: register second user to check """ app = TestApp(main({})) _name = 'mary' res = app.put('/users', _name, status=200) self.assertTrue( 'application/json; charset=UTF-8' in res.headers['Content-Type']) # store the body as json _json = json.loads(res.body) #print(_json['token']) self.assertTrue('0.1dev' in _json['api-version']) self.assertTrue(_name in str(_json['token'])) _token = _json['token'] #print("the token from res: " + _token) # try using an invalid token: get coverage for the valid_token function _invalid_token = _token.replace('-', '') # removing the '-' #print("_invalid_token: " + _invalid_token) _auth_header = {'X-Messaging-Token': str(_invalid_token)} # calling with the invalid_token we expect 401: Unauthorized res2 = app.delete_json('/users', params=_name, headers=_auth_header, status=401) _auth_header = {'X-Messaging-Token': str(_token)} # now we have a token and can authenticate... and delete the user # delete the user #res2 = app.delete('/users', params=_name, res2 = app.delete_json('/users', params=_name, headers=_auth_header, status=200) #print(res2) self.assertTrue('goodbye' in json.loads(res2.body).keys()) self.assertTrue(_name in json.loads(res2.body).values())
class ApplicationTestMixin(object): def setUp(self): super(ApplicationTestMixin, self).setUp() self.config = {"db" : {"url" : "sqlite://"}} self.great = create_app(config=self.config) self.app = TestApp(wsgi.create_app(self.great)) METADATA.create_all(self.great.bin.provide("db")) def create(self, **params): return self.app.post_json(self.URL, params=params).json def delete(self, **params): return self.app.delete_json(self.URL, params=params) def list(self, **params): return self.app.get(self.URL, params=params).json
class Client(object): def __init__(self): self.core = Core(db_type="memory").execute_wsgi() self.test_core = TestApp(self.core) def migrate_in_memory(self, migrations_path, alembic_ini_path=None, connection=None, revision="head"): config = Config(alembic_ini_path) config.set_main_option("script_location", migrations_path) if connection is not None: config.attributes["connection"] = connection command.upgrade(config, revision) def get_api(self, api_url, *auth): response = APIResponse() __api_url = str(api_url) if auth: self.test_core.set_authorization(auth) test_core_response = self.test_core.get(__api_url) response.json = test_core_response.json response.status = test_core_response.status response.status_code = test_core_response.status_code response.body = test_core_response.body response.content_type = test_core_response.content_type return response def post_api(self, api_url, data, *auth): response = APIResponse() __api_url = str(api_url) if auth: self.test_core.set_authorization(auth) test_core_response = self.test_core.post_json(__api_url, params=data) response.json = json.dumps(test_core_response.json) response.status = test_core_response.status response.status_code = test_core_response.status_code response.body = test_core_response.body return response def patch_api(self, api_url, data, *auth): response = APIResponse() __api_url = str(api_url) if auth: self.test_core.set_authorization(auth) test_core_response = self.test_core.patch_json(__api_url, params=data) response.json = json.dumps(test_core_response.json) response.status = test_core_response.status response.status_code = test_core_response.status_code response.body = test_core_response.body return response def put_api(self, api_url, data, *auth): response = APIResponse() __api_url = str(api_url) if auth: self.test_core.set_authorization(auth) test_core_response = self.test_core.put_json(__api_url, params=data) response.json = json.dumps(test_core_response.json) response.status = test_core_response.status response.status_code = test_core_response.status_code response.body = test_core_response.body return response def delete_api(self, api_url, data, *auth): response = APIResponse() __api_url = str(api_url) if auth: self.test_core.set_authorization(auth) test_core_response = self.test_core.delete_json(__api_url, params=data) response.json = json.dumps(test_core_response.json) response.status = test_core_response.status response.status_code = test_core_response.status_code response.body = test_core_response.body return response
class AppTests(unittest.TestCase): def setUp(self): self.maxDiff = None self.client = MongoClient() self.db = self.client[TEST_DB] self.app = TestApp(app.shopping_cart_app) app.db = self.db # Populate database with random data populate_db(TEST_DB) # Add basket for testing purposes # add some products to basket prod = self.db.products.find_one({'name_slug': 'prod-0-0'}) req = self.app.post_json('/api/basket/add', { 'prod_id': str(prod['_id']), 'amount': 4 }) for prod in self.db.products.find(skip=1, limit=5): req = self.app.post_json( '/api/basket/add', { 'basket_id': json.loads(req.body)['_id'], 'prod_id': str(prod['_id']), 'amount': randint(1, 10) }) self.basket = json.loads(req.body) def tearDown(self): self.client.drop_database('shopping-cart-test') def test_get_categories_request(self): req = self.app.get('/api/category') self.assertEqual(req.status, '200 OK') self.assertEqual(req.content_type, 'application/json') def test_get_categories(self): categories = json.loads(app.get_categories()) self.assertEqual(len(categories), self.db.categories.count()) self.assertEqual(sum([item['prod_amount'] for item in categories]), self.db.products.count()) def test_get_category_products_request(self): req = self.app.get('/api/category/cat-0') self.assertEqual(req.status, '200 OK') self.assertEqual(req.content_type, 'application/json') def test_get_category_products(self): cat = self.db.categories.find_one({'name_slug': 'cat-0'}) products = list( self.db.products.find({'cat_id': cat['_id']}, sort=[('name', 1)], limit=app.PRODUCTS_PER_PAGE)) for prod in products: prod['_id'] = str(prod['_id']) del prod['cat_id'] self.assertEqual(json.loads(app.get_products_by_category('cat-0')), products) def get_product_details_request(self): req = self.app.get('/api/product/prod-0-0') self.assertEqual(req.status, '200 OK') self.assertEqual(req.content_type, 'application/json') def test_get_not_existing_product_details_request(self): req = self.app.get('/api/product/somekindofproduct') self.assertEqual(json.loads(req.body), []) def test_get_product_details(self): prod_0_0 = self.db.products.find_one({'name_slug': 'prod-0-0'}) prod_0_0['_id'] = str(prod_0_0['_id']) del prod_0_0['cat_id'] self.assertEqual(json.loads(app.get_product('prod-0-0')), prod_0_0) def test_add_product_to_basket(self): prod = self.db.products.find_one({'name_slug': 'prod-0-0'}) req = self.app.post_json('/api/basket/add', { 'prod_id': str(prod['_id']), 'amount': 2 }) req_data = json.loads(req.body) self.assertEqual(req.status, '200 OK') self.assertEqual(len(req_data['products']), 1) def test_add_existing_product_to_basket(self): prod = self.db.products.find_one({'name_slug': 'prod-0-0'}) req = self.app.post_json('/api/basket/add', { 'prod_id': str(prod['_id']), 'amount': 2 }) req_data = json.loads(req.body) sec_req = self.app.post_json('/api/basket/add', { 'basket_id': req_data['_id'], 'prod_id': str(prod['_id']), 'amount': 3 }) sec_req_data = json.loads(sec_req.body) self.assertEqual(sec_req_data['products'][0]['price'], prod['promo_price']) self.assertEqual(sec_req_data['products'][0]['amount'], 5) def test_remove_product_from_basket(self): req = self.app.delete_json( '/api/basket/remove', { 'basket_id': self.basket['_id'], 'prod_id': str(self.basket['products'][0]['prod_id']) }) self.assertEqual(len(json.loads(req.body)['products']), 5) def test_add_promo_code_to_basket(self): req = self.app.post_json('/api/basket/promocode', { 'basket_id': self.basket['_id'], 'promo_code': 'hydecode' }) req_data = json.loads(req.body) self.assertEqual(len(req_data['promo_codes']), 1) def test_add__not_existing_promo_code_to_basket(self): req = self.app.post_json('/api/basket/promocode', { 'basket_id': self.basket['_id'], 'promo_code': 'qwerty' }) req_data = json.loads(req.body) self.assertEqual(req_data, [])
class FunctionalTests(unittest.TestCase): def setUp(self): import tempfile import os.path from . import main self.tmpdir = tempfile.mkdtemp() dbpath = os.path.join(self.tmpdir, "test.db") uri = "file://" + dbpath settings = { "zodbconn.uri": uri, "pyramid.includes": ["pyramid_zodbconn", "pyramid_tm"], } app = main({}, **settings) self.db = app.registry._zodb_databases[""] from webtest import TestApp self.testapp = TestApp(app) def tearDown(self): import shutil self.db.close() shutil.rmtree(self.tmpdir) def test_root(self): res = self.testapp.get("/", status=200) self.assertTrue(b"" in res.body) def test_add_container(self): res = self.testapp.post_json("/", {"app_id": "my_app"}) res = self.testapp.get("/", status=200) self.assertEqual(["my_app"], res.json_body) with pytest.raises(AppError): self.testapp.post_json("/", {"app_idd": "my_app"}) res = self.testapp.get("/my_app", status=200) res = self.testapp.post_json("/my_app", {"container_id": "iasmartweb"}) res = self.testapp.get("/my_app", status=200) self.assertEqual(["iasmartweb"], res.json_body) def test_add_content(self): res = self.testapp.post_json("/", {"app_id": "my_app"}) res = self.testapp.get("/", status=200) self.assertEqual(["my_app"], res.json_body) with pytest.raises(AppError): self.testapp.post_json("/", {"app_idd": "my_app"}) res = self.testapp.get("/my_app", status=200) res = self.testapp.post_json("/my_app", {"container_id": "iasmartweb"}) res = self.testapp.get("/my_app", status=200) self.assertEqual(["iasmartweb"], res.json_body) res = self.testapp.post_json("/my_app/iasmartweb", {"content_id": "bsuttor"}) res = self.testapp.get("/my_app/iasmartweb", status=200) self.assertEqual(["bsuttor"], res.json_body) def test_remove_content(self): res = self.testapp.post_json("/", {"app_id": "my_app"}) res = self.testapp.post_json("/my_app", {"container_id": "imio"}) res = self.testapp.post_json("/my_app/imio", {"container_id": "iasmartweb"}) res = self.testapp.post_json( "/my_app/imio/iasmartweb", { "content_id": "bsuttor", "username": "******", "email": "*****@*****.**", "fullname": "Benoît Suttor", }, ) res = self.testapp.get("/my_app/imio/iasmartweb/bsuttor", status=200) self.assertEqual(res.json.get("email"), "*****@*****.**") res = self.testapp.get("/my_app/imio/iasmartweb", status=200) self.assertEqual(len(res.json), 1) self.testapp.delete_json("/my_app/imio/iasmartweb/bsuttor") res = self.testapp.get("/my_app/imio/iasmartweb", status=200) self.assertEqual(len(res.json), 0) def test_update_content(self): res = self.testapp.post_json("/", {"app_id": "my_app"}) res = self.testapp.post_json("/my_app", {"container_id": "imio"}) res = self.testapp.post_json("/my_app/imio", {"container_id": "iasmartweb"}) res = self.testapp.post_json( "/my_app/imio/iasmartweb", { "content_id": "bsuttor", "username": "******", "email": "*****@*****.**", "fullname": "Benoît Suttor", }, ) res = self.testapp.get("/my_app/imio/iasmartweb", status=200) self.assertEqual(len(res.json), 1) res = self.testapp.patch_json( "/my_app/imio/iasmartweb/bsuttor", {"email": "*****@*****.**"} ) res = self.testapp.get("/my_app/imio/iasmartweb", status=200) self.assertEqual(len(res.json), 1) res = self.testapp.get("/my_app/imio/iasmartweb/bsuttor", status=200) self.assertEqual(res.json.get("email"), "*****@*****.**") def test_replace_content(self): res = self.testapp.post_json("/", {"app_id": "my_app"}) res = self.testapp.post_json("/my_app", {"container_id": "imio"}) res = self.testapp.post_json("/my_app/imio", {"container_id": "iasmartweb"}) res = self.testapp.post_json( "/my_app/imio/iasmartweb", { "content_id": "bsuttor", "username": "******", "email": "*****@*****.**", "fullname": "Benoît Suttor", }, ) res = self.testapp.get("/my_app/imio/iasmartweb", status=200) self.assertEqual(len(res.json), 1) res = self.testapp.put_json( "/my_app/imio/iasmartweb/bsuttor", { "content_id": "benoit", "username": "******", "email": "*****@*****.**", "fullname": "Ben Suttor", }, ) res = self.testapp.get("/my_app/imio/iasmartweb", status=200) self.assertEqual(len(res.json), 1) res = self.testapp.get("/my_app/imio/iasmartweb/bsuttor", status=404) self.assertEqual( res.body, b"The path my_app/imio/iasmartweb/bsuttor is not found" ) # noqa res = self.testapp.get("/my_app/imio/iasmartweb/benoit", status=200) self.assertEqual(res.json.get("email"), "*****@*****.**") res = self.testapp.get("/my_app/imio/iasmartweb", status=200) self.assertEqual(len(res.json), 1) def test_export_csv(self): res = self.testapp.post_json("/", {"app_id": "my_app"}) res = self.testapp.post_json("/my_app", {"container_id": "imio"}) res = self.testapp.post_json("/my_app/imio", {"container_id": "iasmartweb"}) res = self.testapp.post_json("/my_app/imio", {"container_id": "iaurban"}) res = self.testapp.post_json("/my_app/imio", {"container_id": "iateleservice"}) res = self.testapp.post_json( "/my_app/imio/iasmartweb", { "content_id": "bsuttor", "username": "******", "email": "*****@*****.**", "fullname": "Benoît Suttor", "password": "******", }, ) res = self.testapp.post_json( "/my_app/imio/iasmartweb", { "content_id": "jbond", "username": "******", "email": "*****@*****.**", "fullname": "James Bond", "password": "******", }, ) res = self.testapp.post_json( "/my_app/imio/iaurban", { "content_id": "bsuttor", "username": "******", "email": "*****@*****.**", "fullname": "", "password": "******", }, ) res = self.testapp.post_json( "/my_app/imio/iateleservice", { "content_id": "suttorb", "username": "******", "email": "*****@*****.**", "fullname": "benoît suttor", "password": "******", }, ) res = self.testapp.get("/my_app/imio/csv", status=200) self.assertEqual(res.content_type, "text/csv") self.assertTrue("bsuttor" in str(res.body)) self.assertEqual(len(res.body.decode("utf8").split("\r\n")), 4) def test_export_json(self): res = self.testapp.post_json("/", {"app_id": "my_app"}) res = self.testapp.post_json("/my_app", {"container_id": "imio"}) res = self.testapp.post_json("/my_app/imio", {"container_id": "iasmartweb"}) res = self.testapp.post_json("/my_app/imio", {"container_id": "iaurban"}) res = self.testapp.post_json( "/my_app/imio/iasmartweb", { "content_id": "bsuttor", "username": "******", "email": "*****@*****.**", "fullname": "Benoît Suttor", "password": "******", }, ) res = self.testapp.post_json( "/my_app/imio/iasmartweb", { "content_id": "jbond", "username": "******", "email": "*****@*****.**", "fullname": "James Bond", "password": "******", }, ) res = self.testapp.post_json( "/my_app/imio/iaurban", { "content_id": "bsuttor", "username": "******", "email": "*****@*****.**", "fullname": "", "password": "******", }, ) res = self.testapp.get("/my_app/imio/json", status=200) self.assertEqual(res.content_type, "application/json") self.assertEqual(len(res.json_body["users"]), 3)
class TestHttpHandler(TestCaseWithDatabasePerTest): def setUp(self): super(TestHttpHandler, self).setUp() bottle.debug(True) handler = WimHandler(db=self.db) self.engine = handler.engine self.addCleanup(self.engine.stop_threads) self.app = TestApp(handler.wsgi_app) def populate(self, seeds=None): super(TestHttpHandler, self).populate(seeds or eg.consistent_set()) def test_list_wims(self): # Given some wims are registered in the database self.populate() # when a GET /<tenant_id>/wims request arrives tenant_id = uuid('tenant0') response = self.app.get('/{}/wims'.format(tenant_id)) # then the request should be well succeeded self.assertEqual(response.status_code, OK) # and all the registered wims should be present retrieved_wims = {v['name']: v for v in response.json['wims']} for name in retrieved_wims: identifier = int(name.replace('wim', '')) self.assertDictContainsSubset(eg.wim(identifier), retrieved_wims[name]) def test_show_wim(self): # Given some wims are registered in the database self.populate() # when a GET /<tenant_id>/wims/<wim_id> request arrives tenant_id = uuid('tenant0') wim_id = uuid('wim1') response = self.app.get('/{}/wims/{}'.format(tenant_id, wim_id)) # then the request should be well succeeded self.assertEqual(response.status_code, OK) # and the registered wim (wim1) should be present self.assertDictContainsSubset(eg.wim(1), response.json['wim']) # Moreover, it also works with tenant_id = all response = self.app.get('/any/wims/{}'.format(wim_id)) self.assertEqual(response.status_code, OK) self.assertDictContainsSubset(eg.wim(1), response.json['wim']) def test_show_wim__wim_doesnt_exists(self): # Given wim_id does not refer to any already registered wim self.populate() # when a GET /<tenant_id>/wims/<wim_id> request arrives tenant_id = uuid('tenant0') wim_id = uuid('wim999') response = self.app.get('/{}/wims/{}'.format(tenant_id, wim_id), expect_errors=True) # then the result should not be well succeeded self.assertEqual(response.status_code, Not_Found) def test_show_wim__tenant_doesnt_exists(self): # Given wim_id does not refer to any already registered wim self.populate() # when a GET /<tenant_id>/wims/<wim_id> request arrives tenant_id = uuid('tenant999') wim_id = uuid('wim0') response = self.app.get('/{}/wims/{}'.format(tenant_id, wim_id), expect_errors=True) # then the result should not be well succeeded self.assertEqual(response.status_code, Not_Found) def test_edit_wim(self): # Given a WIM exists in the database self.populate() # when a PUT /wims/<wim_id> request arrives wim_id = uuid('wim1') response = self.app.put_json('/wims/{}'.format(wim_id), {'wim': { 'name': 'My-New-Name' }}) # then the request should be well succeeded self.assertEqual(response.status_code, OK) # and the registered wim (wim1) should be present self.assertDictContainsSubset( merge_dicts(eg.wim(1), name='My-New-Name'), response.json['wim']) def test_edit_wim__port_mappings(self): # Given a WIM exists in the database self.populate() # when a PUT /wims/<wim_id> request arrives wim_id = uuid('wim1') response = self.app.put_json( '/wims/{}'.format(wim_id), { 'wim': dict(name='My-New-Name', config={ 'wim_port_mapping': [{ 'datacenter_name': 'dc0', 'pop_wan_mappings': [{ 'pop_switch_dpid': '00:AA:11:BB:22:CC:33:DD', 'pop_switch_port': 1, 'wan_service_mapping_info': { 'mapping_type': 'dpid-port', 'wan_switch_dpid': 'BB:BB:BB:BB:BB:BB:BB:0A', 'wan_switch_port': 1 } }] }] }) }) # then the request should be well succeeded self.assertEqual(response.status_code, OK) # and the registered wim (wim1) should be present self.assertDictContainsSubset( merge_dicts(eg.wim(1), name='My-New-Name'), response.json['wim']) # and the port mappings hould be updated mappings = response.json['wim']['config']['wim_port_mapping'] self.assertEqual(len(mappings), 1) self.assertEqual(mappings[0]['pop_wan_mappings'][0]['pop_switch_dpid'], '00:AA:11:BB:22:CC:33:DD') def test_delete_wim(self): # Given a WIM exists in the database self.populate() num_accounts = self.count('wim_accounts') num_associations = self.count('wim_nfvo_tenants') num_mappings = self.count('wim_port_mappings') with self.engine.threads_running(): num_threads = len(self.engine.threads) # when a DELETE /wims/<wim_id> request arrives wim_id = uuid('wim1') response = self.app.delete('/wims/{}'.format(wim_id)) num_threads_after = len(self.engine.threads) # then the request should be well succeeded self.assertEqual(response.status_code, OK) self.assertIn('deleted', response.json['result']) # and the registered wim1 should be deleted response = self.app.get('/any/wims/{}'.format(wim_id), expect_errors=True) self.assertEqual(response.status_code, Not_Found) # and all the dependent records in other tables should be deleted: # wim_accounts, wim_nfvo_tenants, wim_port_mappings self.assertEqual(self.count('wim_nfvo_tenants'), num_associations - eg.NUM_TENANTS) self.assertLess(self.count('wim_port_mappings'), num_mappings) self.assertEqual(self.count('wim_accounts'), num_accounts - eg.NUM_TENANTS) # And the threads associated with the wim accounts should be stopped self.assertEqual(num_threads_after, num_threads - eg.NUM_TENANTS) def test_create_wim(self): # Given no WIM exists yet # when a POST /wims request arrives with the right payload response = self.app.post_json('/wims', {'wim': eg.wim(999)}) # then the request should be well succeeded self.assertEqual(response.status_code, OK) self.assertEqual(response.json['wim']['name'], 'wim999') def test_create_wim__port_mappings(self): self.populate() # when a POST /wims request arrives with the right payload response = self.app.post_json( '/wims', { 'wim': merge_dicts(eg.wim(999), config={ 'wim_port_mapping': [{ 'datacenter_name': 'dc0', 'pop_wan_mappings': [{ 'pop_switch_dpid': 'AA:AA:AA:AA:AA:AA:AA:01', 'pop_switch_port': 1, 'wan_service_mapping_info': { 'mapping_type': 'dpid-port', 'wan_switch_dpid': 'BB:BB:BB:BB:BB:BB:BB:01', 'wan_switch_port': 1 } }] }] }) }) # then the request should be well succeeded self.assertEqual(response.status_code, OK) self.assertEqual(response.json['wim']['name'], 'wim999') self.assertEqual( len(response.json['wim']['config']['wim_port_mapping']), 1) def test_create_wim_account(self): # Given a WIM and a NFVO tenant exist but are not associated self.populate([{ 'wims': [eg.wim(0)] }, { 'nfvo_tenants': [eg.tenant(0)] }]) with self.engine.threads_running(): num_threads = len(self.engine.threads) # when a POST /<tenant_id>/wims/<wim_id> arrives response = self.app.post_json( '/{}/wims/{}'.format(uuid('tenant0'), uuid('wim0')), {'wim_account': eg.wim_account(0, 0)}) num_threads_after = len(self.engine.threads) # then a new thread should be created self.assertEqual(num_threads_after, num_threads + 1) # and the request should be well succeeded self.assertEqual(response.status_code, OK) self.assertEqual(response.json['wim_account']['name'], 'wim-account00') # and a new association record should be created association = self.db.get_rows(FROM='wim_nfvo_tenants') assert association self.assertEqual(len(association), 1) self.assertEqual(association[0]['wim_id'], uuid('wim0')) self.assertEqual(association[0]['nfvo_tenant_id'], uuid('tenant0')) self.assertEqual(association[0]['wim_account_id'], response.json['wim_account']['uuid']) def test_create_wim_account__existing_account(self): # Given a WIM, a WIM account and a NFVO tenants exist # But the NFVO and the WIM are not associated self.populate([{ 'wims': [eg.wim(0)] }, { 'nfvo_tenants': [eg.tenant(0)] }, { 'wim_accounts': [eg.wim_account(0, 0)] }]) # when a POST /<tenant_id>/wims/<wim_id> arrives # and it refers to an existing wim account response = self.app.post_json( '/{}/wims/{}'.format(uuid('tenant0'), uuid('wim0')), {'wim_account': { 'name': 'wim-account00' }}) # then the request should be well succeeded self.assertEqual(response.status_code, OK) # and the association should be created association = self.db.get_rows(FROM='wim_nfvo_tenants', WHERE={ 'wim_id': uuid('wim0'), 'nfvo_tenant_id': uuid('tenant0') }) assert association self.assertEqual(len(association), 1) # but no new wim_account should be created wim_accounts = self.db.get_rows(FROM='wim_accounts') self.assertEqual(len(wim_accounts), 1) self.assertEqual(wim_accounts[0]['name'], 'wim-account00') def test_create_wim_account__existing_account__differing(self): # Given a WIM, a WIM account and a NFVO tenants exist # But the NFVO and the WIM are not associated self.populate([{ 'wims': [eg.wim(0)] }, { 'nfvo_tenants': [eg.tenant(0)] }, { 'wim_accounts': [eg.wim_account(0, 0)] }]) # when a POST /<tenant_id>/wims/<wim_id> arrives # and it refers to an existing wim account, # but with different fields response = self.app.post_json('/{}/wims/{}'.format( uuid('tenant0'), uuid('wim0')), { 'wim_account': { 'name': 'wim-account00', 'user': '******', 'password': '******' } }, expect_errors=True) # then the request should not be well succeeded self.assertEqual(response.status_code, Conflict) # some useful message should be displayed response.mustcontain('attempt to overwrite', 'user', 'password') # and the association should not be created association = self.db.get_rows(FROM='wim_nfvo_tenants', WHERE={ 'wim_id': uuid('wim0'), 'nfvo_tenant_id': uuid('tenant0') }) assert not association def test_create_wim_account__association_already_exists(self): # Given a WIM, a WIM account and a NFVO tenants exist # and are correctly associated self.populate() num_assoc_before = self.count('wim_nfvo_tenants') # when a POST /<tenant_id>/wims/<wim_id> arrives trying to connect a # WIM and a tenant for the second time response = self.app.post_json( '/{}/wims/{}'.format(uuid('tenant0'), uuid('wim0')), {'wim_account': { 'user': '******', 'password': '******' }}, expect_errors=True) # then the request should not be well succeeded self.assertEqual(response.status_code, Conflict) # the message should be useful response.mustcontain('There is already', uuid('wim0'), uuid('tenant0')) num_assoc_after = self.count('wim_nfvo_tenants') # and the number of association record should not be increased self.assertEqual(num_assoc_before, num_assoc_after) def test_create_wim__tenant_doesnt_exist(self): # Given a tenant not exists self.populate() # But the user tries to create a wim_account anyway response = self.app.post_json( '/{}/wims/{}'.format(uuid('tenant999'), uuid('wim0')), {'wim_account': { 'user': '******', 'password': '******' }}, expect_errors=True) # then the request should not be well succeeded self.assertEqual(response.status_code, Not_Found) # the message should be useful response.mustcontain('No record was found', uuid('tenant999')) def test_create_wim__wim_doesnt_exist(self): # Given a tenant not exists self.populate() # But the user tries to create a wim_account anyway response = self.app.post_json( '/{}/wims/{}'.format(uuid('tenant0'), uuid('wim999')), {'wim_account': { 'user': '******', 'password': '******' }}, expect_errors=True) # then the request should not be well succeeded self.assertEqual(response.status_code, Not_Found) # the message should be useful response.mustcontain('No record was found', uuid('wim999')) def test_update_wim_account(self): # Given a WIM account connecting a tenant and a WIM exists self.populate() with self.engine.threads_running(): num_threads = len(self.engine.threads) thread = self.engine.threads[uuid('wim-account00')] reload = MagicMock(wraps=thread.reload) with patch.object(thread, 'reload', reload): # when a PUT /<tenant_id>/wims/<wim_id> arrives response = self.app.put_json( '/{}/wims/{}'.format(uuid('tenant0'), uuid('wim0')), {'wim_account': { 'name': 'account888', 'user': '******' }}) num_threads_after = len(self.engine.threads) # then the wim thread should be restarted reload.assert_called_once() # and no thread should be added or removed self.assertEqual(num_threads_after, num_threads) # and the request should be well succeeded self.assertEqual(response.status_code, OK) self.assertEqual(response.json['wim_account']['name'], 'account888') self.assertEqual(response.json['wim_account']['user'], 'user888') def test_update_wim_account__multiple(self): # Given a WIM account connected to several tenants self.populate() with self.engine.threads_running(): # when a PUT /any/wims/<wim_id> arrives response = self.app.put_json( '/any/wims/{}'.format(uuid('wim0')), {'wim_account': { 'user': '******', 'config': { 'x': 888 } }}) # then the request should be well succeeded self.assertEqual(response.status_code, OK) self.assertEqual(len(response.json['wim_accounts']), eg.NUM_TENANTS) for account in response.json['wim_accounts']: self.assertEqual(account['user'], 'user888') self.assertEqual(account['config']['x'], 888) def test_delete_wim_account(self): # Given a WIM account exists and it is connected to a tenant self.populate() num_accounts_before = self.count('wim_accounts') with self.engine.threads_running(): thread = self.engine.threads[uuid('wim-account00')] exit = MagicMock(wraps=thread.exit) num_threads = len(self.engine.threads) with patch.object(thread, 'exit', exit): # when a PUT /<tenant_id>/wims/<wim_id> arrives response = self.app.delete_json('/{}/wims/{}'.format( uuid('tenant0'), uuid('wim0'))) num_threads_after = len(self.engine.threads) # then the wim thread should exit self.assertEqual(num_threads_after, num_threads - 1) exit.assert_called_once() # and the request should be well succeeded self.assertEqual(response.status_code, OK) response.mustcontain('account `wim-account00` deleted') # and the number of wim_accounts should decrease num_accounts_after = self.count('wim_accounts') self.assertEqual(num_accounts_after, num_accounts_before - 1) def test_delete_wim_account__multiple(self): # Given a WIM account exists and it is connected to several tenants self.populate() num_accounts_before = self.count('wim_accounts') with self.engine.threads_running(): # when a PUT /<tenant_id>/wims/<wim_id> arrives response = self.app.delete_json('/any/wims/{}'.format( uuid('wim0'))) # then the request should be well succeeded self.assertEqual(response.status_code, OK) response.mustcontain('account `wim-account00` deleted') response.mustcontain('account `wim-account10` deleted') # and the number of wim_accounts should decrease num_accounts_after = self.count('wim_accounts') self.assertEqual(num_accounts_after, num_accounts_before - eg.NUM_TENANTS) def test_delete_wim_account__doesnt_exist(self): # Given we have a tenant that is not connected to a WIM self.populate() tenant = {'uuid': uuid('tenant888'), 'name': 'tenant888'} self.populate([{'nfvo_tenants': [tenant]}]) num_accounts_before = self.count('wim_accounts') # when a PUT /<tenant_id>/wims/<wim_id> arrives response = self.app.delete('/{}/wims/{}'.format( uuid('tenant888'), uuid('wim0')), expect_errors=True) # then the request should not succeed self.assertEqual(response.status_code, Not_Found) # and the number of wim_accounts should not decrease num_accounts_after = self.count('wim_accounts') self.assertEqual(num_accounts_after, num_accounts_before) def test_create_port_mappings(self): # Given we have a wim and datacenter without any port mappings self.populate([{ 'nfvo_tenants': eg.tenant(0) }] + eg.datacenter_set(888, 0) + eg.wim_set(999, 0)) # when a POST /<tenant_id>/wims/<wim_id>/port_mapping arrives response = self.app.post_json( '/{}/wims/{}/port_mapping'.format(uuid('tenant0'), uuid('wim999')), { 'wim_port_mapping': [{ 'datacenter_name': 'dc888', 'pop_wan_mappings': [{ 'pop_switch_dpid': 'AA:AA:AA:AA:AA:AA:AA:AA', 'pop_switch_port': 1, 'wan_service_mapping_info': { 'mapping_type': 'dpid-port', 'wan_switch_dpid': 'BB:BB:BB:BB:BB:BB:BB:BB', 'wan_switch_port': 1 } }] }] }) # the request should be well succeeded self.assertEqual(response.status_code, OK) # and port mappings should be stored in the database port_mapping = self.db.get_rows(FROM='wim_port_mappings') self.assertEqual(len(port_mapping), 1) def test_get_port_mappings(self): # Given WIMS and datacenters exist with port mappings between them self.populate() # when a GET /<tenant_id>/wims/<wim_id>/port_mapping arrives response = self.app.get('/{}/wims/{}/port_mapping'.format( uuid('tenant0'), uuid('wim0'))) # the request should be well succeeded self.assertEqual(response.status_code, OK) # and we should see port mappings for each WIM, datacenter pair mappings = response.json['wim_port_mapping'] self.assertEqual(len(mappings), eg.NUM_DATACENTERS) # ^ In the fixture set all the datacenters are connected to all wims def test_delete_port_mappings(self): # Given WIMS and datacenters exist with port mappings between them self.populate() num_mappings_before = self.count('wim_port_mappings') # when a DELETE /<tenant_id>/wims/<wim_id>/port_mapping arrives response = self.app.delete('/{}/wims/{}/port_mapping'.format( uuid('tenant0'), uuid('wim0'))) # the request should be well succeeded self.assertEqual(response.status_code, OK) # and the number of port mappings should decrease num_mappings_after = self.count('wim_port_mappings') self.assertEqual(num_mappings_after, num_mappings_before - eg.NUM_DATACENTERS)
class Client(object): def __init__(self): self.test_core = TestApp(Core().execute_wsgi()) def get_api(self, api_url, *auth): response = APIResponse() __api_url = str(api_url) if auth: self.test_core.set_authorization(auth) test_core_response = self.test_core.get(__api_url) response.json = test_core_response.json response.status = test_core_response.status response.status_code = test_core_response.status_code response.body = test_core_response.body response.content_type = test_core_response.content_type return response def post_api(self, api_url, data, *auth): response = APIResponse() __api_url = str(api_url) if auth: self.test_core.set_authorization(auth) test_core_response = self.test_core.post_json(__api_url, params=data) response.json = json.dumps(test_core_response.json) response.status = test_core_response.status response.status_code = test_core_response.status_code response.body = test_core_response.body return response def patch_api(self, api_url, data, *auth): response = APIResponse() __api_url = str(api_url) if auth: self.test_core.set_authorization(auth) test_core_response = self.test_core.patch_json(__api_url, params=data) response.json = json.dumps(test_core_response.json) response.status = test_core_response.status response.status_code = test_core_response.status_code response.body = test_core_response.body return response def put_api(self, api_url, data, *auth): response = APIResponse() __api_url = str(api_url) if auth: self.test_core.set_authorization(auth) test_core_response = self.test_core.put_json(__api_url, params=data) response.json = json.dumps(test_core_response.json) response.status = test_core_response.status response.status_code = test_core_response.status_code response.body = test_core_response.body return response def delete_api(self, api_url, data, *auth): response = APIResponse() __api_url = str(api_url) if auth: self.test_core.set_authorization(auth) test_core_response = self.test_core.delete_json(__api_url, params=data) response.json = json.dumps(test_core_response.json) response.status = test_core_response.status response.status_code = test_core_response.status_code response.body = test_core_response.body return response