diff options
| author | Fabian Mastenbroek <mail.fabianm@gmail.com> | 2021-05-15 13:09:06 +0200 |
|---|---|---|
| committer | Fabian Mastenbroek <mail.fabianm@gmail.com> | 2021-05-18 15:46:40 +0200 |
| commit | 2281d3265423d01e60f8cc088de5a5730bb8a910 (patch) | |
| tree | 8dc81338cfd30845717f1b9025176d26c82fe930 /opendc-web/opendc-web-api/tests/api | |
| parent | 05d2318538eba71ac0555dc5ec146499d9cb0592 (diff) | |
api: Migrate to Flask Restful
This change updates the API to use Flask Restful instead of our own
in-house REST library. This change reduces the maintenance effort and
allows us to drastically simplify the API implementation needed for the
OpenDC v2 API.
Diffstat (limited to 'opendc-web/opendc-web-api/tests/api')
| -rw-r--r-- | opendc-web/opendc-web-api/tests/api/test_portfolios.py | 324 | ||||
| -rw-r--r-- | opendc-web/opendc-web-api/tests/api/test_prefabs.py | 252 | ||||
| -rw-r--r-- | opendc-web/opendc-web-api/tests/api/test_projects.py | 167 | ||||
| -rw-r--r-- | opendc-web/opendc-web-api/tests/api/test_scenarios.py | 135 | ||||
| -rw-r--r-- | opendc-web/opendc-web-api/tests/api/test_schedulers.py | 22 | ||||
| -rw-r--r-- | opendc-web/opendc-web-api/tests/api/test_topologies.py | 140 | ||||
| -rw-r--r-- | opendc-web/opendc-web-api/tests/api/test_traces.py | 40 |
7 files changed, 1080 insertions, 0 deletions
diff --git a/opendc-web/opendc-web-api/tests/api/test_portfolios.py b/opendc-web/opendc-web-api/tests/api/test_portfolios.py new file mode 100644 index 00000000..da7991f6 --- /dev/null +++ b/opendc-web/opendc-web-api/tests/api/test_portfolios.py @@ -0,0 +1,324 @@ +# Copyright (c) 2021 AtLarge Research +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +from opendc.exts import db + +test_id = 24 * '1' +test_id_2 = 24 * '2' + + +def test_get_portfolio_non_existing(client, mocker): + mocker.patch.object(db, 'fetch_one', return_value=None) + assert '404' in client.get(f'/portfolios/{test_id}').status + + +def test_get_portfolio_no_authorizations(client, mocker): + mocker.patch.object(db, 'fetch_one', return_value={'projectId': test_id, 'authorizations': []}) + res = client.get(f'/portfolios/{test_id}') + assert '403' in res.status + + +def test_get_portfolio_not_authorized(client, mocker): + mocker.patch.object(db, + 'fetch_one', + return_value={ + 'projectId': test_id, + '_id': test_id, + 'authorizations': [] + }) + res = client.get(f'/portfolios/{test_id}') + assert '403' in res.status + + +def test_get_portfolio(client, mocker): + mocker.patch.object(db, + 'fetch_one', + return_value={ + 'projectId': test_id, + '_id': test_id, + 'authorizations': [{ + 'userId': 'test', + 'level': 'EDIT' + }] + }) + res = client.get(f'/portfolios/{test_id}') + assert '200' in res.status + + +def test_update_portfolio_missing_parameter(client): + assert '400' in client.put(f'/portfolios/{test_id}').status + + +def test_update_portfolio_non_existing(client, mocker): + mocker.patch.object(db, 'fetch_one', return_value=None) + assert '404' in client.put(f'/portfolios/{test_id}', json={ + 'portfolio': { + 'name': 'test', + 'targets': { + 'enabledMetrics': ['test'], + 'repeatsPerScenario': 2 + } + } + }).status + + +def test_update_portfolio_not_authorized(client, mocker): + mocker.patch.object(db, + 'fetch_one', + return_value={ + '_id': test_id, + 'projectId': test_id, + 'authorizations': [{ + 'userId': 'test', + 'level': 'VIEW' + }] + }) + mocker.patch.object(db, 'update', return_value={}) + assert '403' in client.put(f'/portfolios/{test_id}', json={ + 'portfolio': { + 'name': 'test', + 'targets': { + 'enabledMetrics': ['test'], + 'repeatsPerScenario': 2 + } + } + }).status + + +def test_update_portfolio(client, mocker): + mocker.patch.object(db, + 'fetch_one', + return_value={ + '_id': test_id, + 'projectId': test_id, + 'authorizations': [{ + 'userId': 'test', + 'level': 'OWN' + }], + 'targets': { + 'enabledMetrics': [], + 'repeatsPerScenario': 1 + } + }) + mocker.patch.object(db, 'update', return_value={}) + + res = client.put(f'/portfolios/{test_id}', json={'portfolio': { + 'name': 'test', + 'targets': { + 'enabledMetrics': ['test'], + 'repeatsPerScenario': 2 + } + }}) + assert '200' in res.status + + +def test_delete_project_non_existing(client, mocker): + mocker.patch.object(db, 'fetch_one', return_value=None) + assert '404' in client.delete(f'/portfolios/{test_id}').status + + +def test_delete_project_different_user(client, mocker): + mocker.patch.object(db, + 'fetch_one', + return_value={ + '_id': test_id, + 'projectId': test_id, + 'googleId': 'other_test', + 'authorizations': [{ + 'userId': 'test', + 'level': 'VIEW' + }] + }) + mocker.patch.object(db, 'delete_one', return_value=None) + assert '403' in client.delete(f'/portfolios/{test_id}').status + + +def test_delete_project(client, mocker): + mocker.patch.object(db, + 'fetch_one', + return_value={ + '_id': test_id, + 'projectId': test_id, + 'googleId': 'test', + 'portfolioIds': [test_id], + 'authorizations': [{ + 'userId': 'test', + 'level': 'OWN' + }] + }) + mocker.patch.object(db, 'delete_one', return_value={}) + mocker.patch.object(db, 'update', return_value=None) + res = client.delete(f'/portfolios/{test_id}') + assert '200' in res.status + + +def test_add_topology_missing_parameter(client, mocker): + mocker.patch.object(db, + 'fetch_one', + return_value={ + '_id': test_id, + 'projectId': test_id, + 'googleId': 'test', + 'portfolioIds': [test_id], + 'authorizations': [{ + 'userId': 'test', + 'level': 'OWN' + }] + }) + assert '400' in client.post(f'/projects/{test_id}/topologies').status + + +def test_add_topology(client, mocker): + mocker.patch.object(db, + 'fetch_one', + return_value={ + '_id': test_id, + 'authorizations': [{ + 'userId': 'test', + 'level': 'OWN' + }], + 'topologyIds': [] + }) + mocker.patch.object(db, + 'insert', + return_value={ + '_id': test_id, + 'datetimeCreated': '000', + 'datetimeLastEdited': '000', + 'topologyIds': [] + }) + mocker.patch.object(db, 'update', return_value={}) + res = client.post(f'/projects/{test_id}/topologies', json={'topology': {'name': 'test project', 'rooms': []}}) + assert 'rooms' in res.json['data'] + assert '200' in res.status + + +def test_add_topology_not_authorized(client, mocker): + mocker.patch.object(db, + 'fetch_one', + return_value={ + '_id': test_id, + 'projectId': test_id, + 'authorizations': [{ + 'userId': 'test', + 'level': 'VIEW' + }] + }) + assert '403' in client.post(f'/projects/{test_id}/topologies', + json={ + 'topology': { + 'name': 'test_topology', + 'rooms': [] + } + }).status + + +def test_add_portfolio_missing_parameter(client, mocker): + mocker.patch.object(db, + 'fetch_one', + return_value={ + '_id': test_id, + 'projectId': test_id, + 'googleId': 'test', + 'portfolioIds': [test_id], + 'authorizations': [{ + 'userId': 'test', + 'level': 'OWN' + }] + }) + assert '400' in client.post(f'/projects/{test_id}/portfolios').status + + +def test_add_portfolio_non_existing_project(client, mocker): + mocker.patch.object(db, 'fetch_one', return_value=None) + assert '404' in client.post(f'/projects/{test_id}/portfolios', + json={ + 'portfolio': { + 'name': 'test', + 'targets': { + 'enabledMetrics': ['test'], + 'repeatsPerScenario': 2 + } + } + }).status + + +def test_add_portfolio_not_authorized(client, mocker): + mocker.patch.object(db, + 'fetch_one', + return_value={ + '_id': test_id, + 'projectId': test_id, + 'authorizations': [{ + 'userId': 'test', + 'level': 'VIEW' + }] + }) + assert '403' in client.post(f'/projects/{test_id}/portfolios', + json={ + 'portfolio': { + 'name': 'test', + 'targets': { + 'enabledMetrics': ['test'], + 'repeatsPerScenario': 2 + } + } + }).status + + +def test_add_portfolio(client, mocker): + mocker.patch.object(db, + 'fetch_one', + return_value={ + '_id': test_id, + 'projectId': test_id, + 'portfolioIds': [test_id], + 'authorizations': [{ + 'userId': 'test', + 'level': 'EDIT' + }] + }) + mocker.patch.object(db, + 'insert', + return_value={ + '_id': test_id, + 'name': 'test', + 'targets': { + 'enabledMetrics': ['test'], + 'repeatsPerScenario': 2 + }, + 'projectId': test_id, + 'scenarioIds': [], + }) + mocker.patch.object(db, 'update', return_value=None) + res = client.post( + f'/projects/{test_id}/portfolios', + json={ + 'portfolio': { + 'name': 'test', + 'targets': { + 'enabledMetrics': ['test'], + 'repeatsPerScenario': 2 + } + } + }) + assert 'projectId' in res.json['data'] + assert 'scenarioIds' in res.json['data'] + assert '200' in res.status diff --git a/opendc-web/opendc-web-api/tests/api/test_prefabs.py b/opendc-web/opendc-web-api/tests/api/test_prefabs.py new file mode 100644 index 00000000..ea3d92d6 --- /dev/null +++ b/opendc-web/opendc-web-api/tests/api/test_prefabs.py @@ -0,0 +1,252 @@ +# Copyright (c) 2021 AtLarge Research +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +from unittest.mock import Mock +from opendc.exts import db + +test_id = 24 * '1' +test_id_2 = 24 * '2' + + +def test_add_prefab_missing_parameter(client): + assert '400' in client.post('/prefabs/').status + + +def test_add_prefab(client, mocker): + mocker.patch.object(db, 'fetch_one', return_value={'_id': test_id, 'authorizations': []}) + mocker.patch.object(db, + 'insert', + return_value={ + '_id': test_id, + 'datetimeCreated': '000', + 'datetimeLastEdited': '000', + 'authorId': test_id + }) + res = client.post('/prefabs/', json={'prefab': {'name': 'test prefab'}}) + assert 'datetimeCreated' in res.json['data'] + assert 'datetimeLastEdited' in res.json['data'] + assert 'authorId' in res.json['data'] + assert '200' in res.status + + +def test_get_prefabs(client, mocker): + db.fetch_all = Mock() + mocker.patch.object(db, 'fetch_one', return_value={'_id': test_id}) + db.fetch_all.side_effect = [ + [{ + '_id': test_id, + 'datetimeCreated': '000', + 'datetimeLastEdited': '000', + 'authorId': test_id, + 'visibility' : 'private' + }, + { + '_id': '2' * 24, + 'datetimeCreated': '000', + 'datetimeLastEdited': '000', + 'authorId': test_id, + 'visibility' : 'private' + }, + { + '_id': '3' * 24, + 'datetimeCreated': '000', + 'datetimeLastEdited': '000', + 'authorId': test_id, + 'visibility' : 'public' + }, + { + '_id': '4' * 24, + 'datetimeCreated': '000', + 'datetimeLastEdited': '000', + 'authorId': test_id, + 'visibility' : 'public' + }], + [{ + '_id': '5' * 24, + 'datetimeCreated': '000', + 'datetimeLastEdited': '000', + 'authorId': '2' * 24, + 'visibility' : 'public' + }, + { + '_id': '6' * 24, + 'datetimeCreated': '000', + 'datetimeLastEdited': '000', + 'authorId': '2' * 24, + 'visibility' : 'public' + }, + { + '_id': '7' * 24, + 'datetimeCreated': '000', + 'datetimeLastEdited': '000', + 'authorId': '2' * 24, + 'visibility' : 'public' + }, + { + '_id': '8' * 24, + 'datetimeCreated': '000', + 'datetimeLastEdited': '000', + 'authorId': '2' * 24, + 'visibility' : 'public' + }] + ] + mocker.patch.object(db, 'fetch_one', return_value={'_id': test_id}) + res = client.get('/prefabs/') + assert '200' in res.status + + +def test_get_prefab_non_existing(client, mocker): + mocker.patch.object(db, 'fetch_one', return_value=None) + assert '404' in client.get(f'/prefabs/{test_id}').status + + +def test_get_private_prefab_not_authorized(client, mocker): + db.fetch_one = Mock() + db.fetch_one.side_effect = [{ + '_id': test_id, + 'name': 'test prefab', + 'authorId': test_id_2, + 'visibility': 'private', + 'rack': {} + }, + { + '_id': test_id + } + ] + res = client.get(f'/prefabs/{test_id}') + assert '403' in res.status + + +def test_get_private_prefab(client, mocker): + db.fetch_one = Mock() + db.fetch_one.side_effect = [{ + '_id': test_id, + 'name': 'test prefab', + 'authorId': 'test', + 'visibility': 'private', + 'rack': {} + }, + { + '_id': test_id + } + ] + res = client.get(f'/prefabs/{test_id}') + assert '200' in res.status + + +def test_get_public_prefab(client, mocker): + db.fetch_one = Mock() + db.fetch_one.side_effect = [{ + '_id': test_id, + 'name': 'test prefab', + 'authorId': test_id_2, + 'visibility': 'public', + 'rack': {} + }, + { + '_id': test_id + } + ] + res = client.get(f'/prefabs/{test_id}') + assert '200' in res.status + + +def test_update_prefab_missing_parameter(client): + assert '400' in client.put(f'/prefabs/{test_id}').status + + +def test_update_prefab_non_existing(client, mocker): + mocker.patch.object(db, 'fetch_one', return_value=None) + assert '404' in client.put(f'/prefabs/{test_id}', json={'prefab': {'name': 'S'}}).status + + +def test_update_prefab_not_authorized(client, mocker): + db.fetch_one = Mock() + db.fetch_one.side_effect = [{ + '_id': test_id, + 'name': 'test prefab', + 'authorId': test_id_2, + 'visibility': 'private', + 'rack': {} + }, + { + '_id': test_id + } + ] + mocker.patch.object(db, 'update', return_value={}) + assert '403' in client.put(f'/prefabs/{test_id}', json={'prefab': {'name': 'test prefab', 'rack': {}}}).status + + +def test_update_prefab(client, mocker): + db.fetch_one = Mock() + db.fetch_one.side_effect = [{ + '_id': test_id, + 'name': 'test prefab', + 'authorId': 'test', + 'visibility': 'private', + 'rack': {} + }, + { + '_id': test_id + } + ] + mocker.patch.object(db, 'update', return_value={}) + res = client.put(f'/prefabs/{test_id}', json={'prefab': {'name': 'test prefab', 'rack': {}}}) + assert '200' in res.status + + +def test_delete_prefab_non_existing(client, mocker): + mocker.patch.object(db, 'fetch_one', return_value=None) + assert '404' in client.delete(f'/prefabs/{test_id}').status + + +def test_delete_prefab_different_user(client, mocker): + db.fetch_one = Mock() + db.fetch_one.side_effect = [{ + '_id': test_id, + 'name': 'test prefab', + 'authorId': test_id_2, + 'visibility': 'private', + 'rack': {} + }, + { + '_id': test_id + } + ] + mocker.patch.object(db, 'delete_one', return_value=None) + assert '403' in client.delete(f'/prefabs/{test_id}').status + + +def test_delete_prefab(client, mocker): + db.fetch_one = Mock() + db.fetch_one.side_effect = [{ + '_id': test_id, + 'name': 'test prefab', + 'authorId': 'test', + 'visibility': 'private', + 'rack': {} + }, + { + '_id': test_id + } + ] + mocker.patch.object(db, 'delete_one', return_value={'prefab': {'name': 'name'}}) + res = client.delete(f'/prefabs/{test_id}') + assert '200' in res.status diff --git a/opendc-web/opendc-web-api/tests/api/test_projects.py b/opendc-web/opendc-web-api/tests/api/test_projects.py new file mode 100644 index 00000000..c4c82e0d --- /dev/null +++ b/opendc-web/opendc-web-api/tests/api/test_projects.py @@ -0,0 +1,167 @@ +# Copyright (c) 2021 AtLarge Research +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +from opendc.exts import db + +test_id = 24 * '1' + + +def test_get_user_projects(client, mocker): + mocker.patch.object(db, 'fetch_all', return_value={'_id': test_id, 'authorizations': [{'userId': 'test', + 'level': 'OWN'}]}) + res = client.get('/projects/') + assert '200' in res.status + + +def test_add_project_missing_parameter(client): + assert '400' in client.post('/projects/').status + + +def test_add_project(client, mocker): + mocker.patch.object(db, 'fetch_one', return_value={'_id': test_id, 'authorizations': []}) + mocker.patch.object(db, + 'insert', + return_value={ + '_id': test_id, + 'datetimeCreated': '000', + 'datetimeLastEdited': '000', + 'topologyIds': [] + }) + mocker.patch.object(db, 'update', return_value={}) + res = client.post('/projects/', json={'project': {'name': 'test project'}}) + assert 'datetimeCreated' in res.json['data'] + assert 'datetimeLastEdited' in res.json['data'] + assert 'topologyIds' in res.json['data'] + assert '200' in res.status + + +def test_get_project_non_existing(client, mocker): + mocker.patch.object(db, 'fetch_one', return_value=None) + assert '404' in client.get(f'/projects/{test_id}').status + + +def test_get_project_no_authorizations(client, mocker): + mocker.patch.object(db, 'fetch_one', return_value={'authorizations': []}) + res = client.get(f'/projects/{test_id}') + assert '403' in res.status + + +def test_get_project_not_authorized(client, mocker): + mocker.patch.object(db, + 'fetch_one', + return_value={ + '_id': test_id, + 'authorizations': [] + }) + res = client.get(f'/projects/{test_id}') + assert '403' in res.status + + +def test_get_project(client, mocker): + mocker.patch.object(db, + 'fetch_one', + return_value={ + '_id': test_id, + 'authorizations': [{ + 'userId': 'test', + 'level': 'EDIT' + }] + }) + res = client.get(f'/projects/{test_id}') + assert '200' in res.status + + +def test_update_project_missing_parameter(client): + assert '400' in client.put(f'/projects/{test_id}').status + + +def test_update_project_non_existing(client, mocker): + mocker.patch.object(db, 'fetch_one', return_value=None) + assert '404' in client.put(f'/projects/{test_id}', json={'project': {'name': 'S'}}).status + + +def test_update_project_not_authorized(client, mocker): + mocker.patch.object(db, + 'fetch_one', + return_value={ + '_id': test_id, + 'authorizations': [{ + 'userId': 'test', + 'level': 'VIEW' + }] + }) + mocker.patch.object(db, 'update', return_value={}) + assert '403' in client.put(f'/projects/{test_id}', json={'project': {'name': 'S'}}).status + + +def test_update_project(client, mocker): + mocker.patch.object(db, + 'fetch_one', + return_value={ + '_id': test_id, + 'authorizations': [{ + 'userId': 'test', + 'level': 'OWN' + }] + }) + mocker.patch.object(db, 'update', return_value={}) + + res = client.put(f'/projects/{test_id}', json={'project': {'name': 'S'}}) + assert '200' in res.status + + +def test_delete_project_non_existing(client, mocker): + mocker.patch.object(db, 'fetch_one', return_value=None) + assert '404' in client.delete(f'/projects/{test_id}').status + + +def test_delete_project_different_user(client, mocker): + mocker.patch.object(db, + 'fetch_one', + return_value={ + '_id': test_id, + 'googleId': 'other_test', + 'authorizations': [{ + 'userId': 'test', + 'level': 'VIEW' + }], + 'topologyIds': [] + }) + mocker.patch.object(db, 'delete_one', return_value=None) + assert '403' in client.delete(f'/projects/{test_id}').status + + +def test_delete_project(client, mocker): + mocker.patch.object(db, + 'fetch_one', + return_value={ + '_id': test_id, + 'googleId': 'test', + 'authorizations': [{ + 'userId': 'test', + 'level': 'OWN' + }], + 'topologyIds': [], + 'portfolioIds': [], + }) + mocker.patch.object(db, 'update', return_value=None) + mocker.patch.object(db, 'delete_one', return_value={'googleId': 'test'}) + res = client.delete(f'/projects/{test_id}') + assert '200' in res.status diff --git a/opendc-web/opendc-web-api/tests/api/test_scenarios.py b/opendc-web/opendc-web-api/tests/api/test_scenarios.py new file mode 100644 index 00000000..bdd5c4a3 --- /dev/null +++ b/opendc-web/opendc-web-api/tests/api/test_scenarios.py @@ -0,0 +1,135 @@ +# Copyright (c) 2021 AtLarge Research +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +from opendc.exts import db + +test_id = 24 * '1' +test_id_2 = 24 * '2' + + +def test_get_scenario_non_existing(client, mocker): + mocker.patch.object(db, 'fetch_one', return_value=None) + assert '404' in client.get(f'/scenarios/{test_id}').status + + +def test_get_scenario_no_authorizations(client, mocker): + m = mocker.MagicMock() + m.side_effect = ({'portfolioId': test_id}, {'projectId': test_id}, {'authorizations': []}) + mocker.patch.object(db, 'fetch_one', m) + res = client.get(f'/scenarios/{test_id}') + assert '403' in res.status + + +def test_get_scenario(client, mocker): + mocker.patch.object(db, + 'fetch_one', + side_effect=[ + {'portfolioId': test_id}, + {'projectId': test_id}, + {'authorizations': + [{'userId': 'test', 'level': 'OWN'}] + }]) + res = client.get(f'/scenarios/{test_id}') + assert '200' in res.status + + +def test_update_scenario_missing_parameter(client): + assert '400' in client.put(f'/scenarios/{test_id}').status + + +def test_update_scenario_non_existing(client, mocker): + mocker.patch.object(db, 'fetch_one', return_value=None) + assert '404' in client.put(f'/scenarios/{test_id}', json={ + 'scenario': { + 'name': 'test', + } + }).status + + +def test_update_scenario_not_authorized(client, mocker): + mocker.patch.object(db, + 'fetch_one', + side_effect=[ + {'portfolioId': test_id}, + {'projectId': test_id}, + {'authorizations': + [{'userId': 'test', 'level': 'VIEW'}] + }]) + mocker.patch.object(db, 'update', return_value={}) + assert '403' in client.put(f'/scenarios/{test_id}', json={ + 'scenario': { + 'name': 'test', + } + }).status + + +def test_update_scenario(client, mocker): + mocker.patch.object(db, + 'fetch_one', + side_effect=[ + {'_id': test_id, 'portfolioId': test_id}, + {'projectId': test_id}, + {'authorizations': + [{'userId': 'test', 'level': 'OWN'}] + }]) + mocker.patch.object(db, 'update', return_value={}) + + res = client.put(f'/scenarios/{test_id}', json={'scenario': { + 'name': 'test', + }}) + assert '200' in res.status + + +def test_delete_project_non_existing(client, mocker): + mocker.patch.object(db, 'fetch_one', return_value=None) + assert '404' in client.delete(f'/scenarios/{test_id}').status + + +def test_delete_project_different_user(client, mocker): + mocker.patch.object(db, + 'fetch_one', + side_effect=[ + {'_id': test_id, 'portfolioId': test_id}, + {'projectId': test_id}, + {'authorizations': + [{'userId': 'test', 'level': 'VIEW'}] + }]) + mocker.patch.object(db, 'delete_one', return_value=None) + assert '403' in client.delete(f'/scenarios/{test_id}').status + + +def test_delete_project(client, mocker): + mocker.patch.object(db, + 'fetch_one', + return_value={ + '_id': test_id, + 'projectId': test_id, + 'portfolioId': test_id, + 'googleId': 'test', + 'scenarioIds': [test_id], + 'authorizations': [{ + 'userId': 'test', + 'level': 'OWN' + }] + }) + mocker.patch.object(db, 'delete_one', return_value={}) + mocker.patch.object(db, 'update', return_value=None) + res = client.delete(f'/scenarios/{test_id}') + assert '200' in res.status diff --git a/opendc-web/opendc-web-api/tests/api/test_schedulers.py b/opendc-web/opendc-web-api/tests/api/test_schedulers.py new file mode 100644 index 00000000..5d9e6995 --- /dev/null +++ b/opendc-web/opendc-web-api/tests/api/test_schedulers.py @@ -0,0 +1,22 @@ +# Copyright (c) 2021 AtLarge Research +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +def test_get_schedulers(client): + assert '200' in client.get('/schedulers/').status diff --git a/opendc-web/opendc-web-api/tests/api/test_topologies.py b/opendc-web/opendc-web-api/tests/api/test_topologies.py new file mode 100644 index 00000000..6e7c54ef --- /dev/null +++ b/opendc-web/opendc-web-api/tests/api/test_topologies.py @@ -0,0 +1,140 @@ +# Copyright (c) 2021 AtLarge Research +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +from opendc.exts import db + +test_id = 24 * '1' +test_id_2 = 24 * '2' + + +def test_get_topology(client, mocker): + mocker.patch.object(db, + 'fetch_one', + return_value={ + '_id': test_id, + 'projectId': test_id, + 'authorizations': [{ + 'userId': 'test', + 'level': 'EDIT' + }] + }) + res = client.get(f'/topologies/{test_id}') + assert '200' in res.status + + +def test_get_topology_non_existing(client, mocker): + mocker.patch.object(db, 'fetch_one', return_value=None) + assert '404' in client.get('/topologies/1').status + + +def test_get_topology_not_authorized(client, mocker): + mocker.patch.object(db, + 'fetch_one', + return_value={ + '_id': test_id, + 'projectId': test_id, + 'authorizations': [] + }) + res = client.get(f'/topologies/{test_id}') + assert '403' in res.status + + +def test_get_topology_no_authorizations(client, mocker): + mocker.patch.object(db, 'fetch_one', return_value={'projectId': test_id, 'authorizations': []}) + res = client.get(f'/topologies/{test_id}') + assert '403' in res.status + + +def test_update_topology_missing_parameter(client, mocker): + mocker.patch.object(db, + 'fetch_one', + return_value={ + '_id': test_id, + 'projectId': test_id, + 'authorizations': [] + }) + assert '400' in client.put(f'/topologies/{test_id}').status + + +def test_update_topology_non_existent(client, mocker): + mocker.patch.object(db, 'fetch_one', return_value=None) + assert '404' in client.put(f'/topologies/{test_id}', json={'topology': {'name': 'test_topology', 'rooms': []}}).status + + +def test_update_topology_not_authorized(client, mocker): + mocker.patch.object(db, + 'fetch_one', + return_value={ + '_id': test_id, + 'projectId': test_id, + 'authorizations': [] + }) + mocker.patch.object(db, 'update', return_value={}) + assert '403' in client.put(f'/topologies/{test_id}', json={ + 'topology': { + 'name': 'updated_topology', + 'rooms': [] + } + }).status + + +def test_update_topology(client, mocker): + mocker.patch.object(db, + 'fetch_one', + return_value={ + '_id': test_id, + 'projectId': test_id, + 'authorizations': [{ + 'userId': 'test', + 'level': 'OWN' + }] + }) + mocker.patch.object(db, 'update', return_value={}) + + assert '200' in client.put(f'/topologies/{test_id}', json={ + 'topology': { + 'name': 'updated_topology', + 'rooms': [] + } + }).status + + +def test_delete_topology(client, mocker): + mocker.patch.object(db, + 'fetch_one', + return_value={ + '_id': test_id, + 'projectId': test_id, + 'googleId': 'test', + 'topologyIds': [test_id], + 'authorizations': [{ + 'userId': 'test', + 'level': 'OWN' + }] + }) + mocker.patch.object(db, 'delete_one', return_value={}) + mocker.patch.object(db, 'update', return_value=None) + res = client.delete(f'/topologies/{test_id}') + assert '200' in res.status + + +def test_delete_nonexistent_topology(client, mocker): + mocker.patch.object(db, 'fetch_one', return_value=None) + assert '404' in client.delete(f'/topologies/{test_id}').status diff --git a/opendc-web/opendc-web-api/tests/api/test_traces.py b/opendc-web/opendc-web-api/tests/api/test_traces.py new file mode 100644 index 00000000..0b252c2f --- /dev/null +++ b/opendc-web/opendc-web-api/tests/api/test_traces.py @@ -0,0 +1,40 @@ +# Copyright (c) 2021 AtLarge Research +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +from opendc.exts import db + +test_id = 24 * '1' + + +def test_get_traces(client, mocker): + mocker.patch.object(db, 'fetch_all', return_value=[]) + assert '200' in client.get('/traces/').status + + +def test_get_trace_non_existing(client, mocker): + mocker.patch.object(db, 'fetch_one', return_value=None) + assert '404' in client.get(f'/traces/{test_id}').status + + +def test_get_trace(client, mocker): + mocker.patch.object(db, 'fetch_one', return_value={'name': 'test trace'}) + res = client.get(f'/traces/{test_id}') + assert 'name' in res.json['data'] + assert '200' in res.status |
