Example #1
0
    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())
Example #2
0
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
Example #4
0
    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())
Example #5
0
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
Example #6
0
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
Example #7
0
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, [])
Example #8
0
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)
Example #9
0
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)
Example #10
0
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