Blame appqos/tests/test_rest_app.py

Packit Service 8a4b7a
################################################################################
Packit Service 8a4b7a
# BSD LICENSE
Packit Service 8a4b7a
#
Packit Service 8a4b7a
# Copyright(c) 2019-2020 Intel Corporation. All rights reserved.
Packit Service 8a4b7a
# All rights reserved.
Packit Service 8a4b7a
#
Packit Service 8a4b7a
# Redistribution and use in source and binary forms, with or without
Packit Service 8a4b7a
# modification, are permitted provided that the following conditions
Packit Service 8a4b7a
# are met:
Packit Service 8a4b7a
#
Packit Service 8a4b7a
#   * Redistributions of source code must retain the above copyright
Packit Service 8a4b7a
#     notice, this list of conditions and the following disclaimer.
Packit Service 8a4b7a
#   * Redistributions in binary form must reproduce the above copyright
Packit Service 8a4b7a
#     notice, this list of conditions and the following disclaimer in
Packit Service 8a4b7a
#     the documentation and/or other materials provided with the
Packit Service 8a4b7a
#     distribution.
Packit Service 8a4b7a
#   * Neither the name of Intel Corporation nor the names of its
Packit Service 8a4b7a
#     contributors may be used to endorse or promote products derived
Packit Service 8a4b7a
#     from this software without specific prior written permission.
Packit Service 8a4b7a
#
Packit Service 8a4b7a
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
Packit Service 8a4b7a
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
Packit Service 8a4b7a
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
Packit Service 8a4b7a
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
Packit Service 8a4b7a
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
Packit Service 8a4b7a
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
Packit Service 8a4b7a
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
Packit Service 8a4b7a
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
Packit Service 8a4b7a
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Packit Service 8a4b7a
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
Packit Service 8a4b7a
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit Service 8a4b7a
################################################################################
Packit Service 8a4b7a
Packit Service 8a4b7a
"""
Packit Service 8a4b7a
Unit tests for rest module APPs
Packit Service 8a4b7a
"""
Packit Service 8a4b7a
Packit Service 8a4b7a
import json
Packit Service 8a4b7a
from jsonschema import validate
Packit Service 8a4b7a
import mock
Packit Service 8a4b7a
import pytest
Packit Service 8a4b7a
Packit Service 8a4b7a
import common
Packit Service 8a4b7a
import caps
Packit Service 8a4b7a
import pid_ops
Packit Service 8a4b7a
Packit Service 8a4b7a
from rest_common import get_config, load_json_schema, REST, CONFIG_EMPTY
Packit Service 8a4b7a
Packit Service 8a4b7a
Packit Service 8a4b7a
class TestApps:
Packit Service 8a4b7a
    @mock.patch("common.CONFIG_STORE.get_config", new=get_config)
Packit Service 8a4b7a
    def test_get(self):
Packit Service 8a4b7a
        response = REST.get("/apps")
Packit Service 8a4b7a
        data = json.loads(response.data.decode('utf-8'))
Packit Service 8a4b7a
Packit Service 8a4b7a
        assert response.status_code == 200
Packit Service 8a4b7a
Packit Service 8a4b7a
        # validate get all pools response schema
Packit Service 8a4b7a
        schema, resolver = load_json_schema('get_app_all_response.json')
Packit Service 8a4b7a
        validate(data, schema, resolver=resolver)
Packit Service 8a4b7a
Packit Service 8a4b7a
        # assert 3 apps are returned
Packit Service 8a4b7a
        # structure, types and required fields are validated using schema
Packit Service 8a4b7a
        assert len(data) == 3
Packit Service 8a4b7a
Packit Service 8a4b7a
Packit Service 8a4b7a
    @mock.patch("common.CONFIG_STORE.get_config", mock.MagicMock(return_value=CONFIG_EMPTY))
Packit Service 8a4b7a
    def test_get_empty(self):
Packit Service 8a4b7a
        response = REST.get("/apps")
Packit Service 8a4b7a
        data = json.loads(response.data.decode('utf-8'))
Packit Service 8a4b7a
Packit Service 8a4b7a
        # assert 0 apps are returned
Packit Service 8a4b7a
        assert response.status_code == 404
Packit Service 8a4b7a
        assert "No apps in config" in data["message"]
Packit Service 8a4b7a
Packit Service 8a4b7a
Packit Service 8a4b7a
    @mock.patch("common.CONFIG_STORE.get_config", new=get_config)
Packit Service 8a4b7a
    @mock.patch("common.PQOS_API.check_core", mock.MagicMock(return_value=True))
Packit Service 8a4b7a
    @mock.patch("pid_ops.is_pid_valid", mock.MagicMock(return_value=True))
Packit Service 8a4b7a
    @mock.patch("caps.cat_supported", mock.MagicMock(return_value=True))
Packit Service 8a4b7a
    @mock.patch("caps.mba_supported", mock.MagicMock(return_value=True))
Packit Service 8a4b7a
    @mock.patch("power.validate_power_profiles", mock.MagicMock(return_value=True))
Packit Service 8a4b7a
    @pytest.mark.parametrize("app_config", [
Packit Service 8a4b7a
            {"pool_id": 2, "name":"hello","cores":[2, 3],"pids":[11]},
Packit Service 8a4b7a
            {"pool_id": 2, "name":"hello", "pids": [12]}                                    # no cores
Packit Service 8a4b7a
        ])
Packit Service 8a4b7a
    def test_post(self, app_config):
Packit Service 8a4b7a
        with mock.patch('common.CONFIG_STORE.set_config') as func_mock,\
Packit Service 8a4b7a
             mock.patch('pid_ops.is_pid_valid', return_value=True):
Packit Service 8a4b7a
            response = REST.post("/apps", app_config)
Packit Service 8a4b7a
            func_mock.assert_called_once()
Packit Service 8a4b7a
        data = json.loads(response.data.decode('utf-8'))
Packit Service 8a4b7a
Packit Service 8a4b7a
        # validate response schema
Packit Service 8a4b7a
        schema, resolver = load_json_schema('add_app_response.json')
Packit Service 8a4b7a
        validate(data, schema, resolver=resolver)
Packit Service 8a4b7a
Packit Service 8a4b7a
        assert response.status_code == 201
Packit Service 8a4b7a
        assert 'id' in data
Packit Service 8a4b7a
Packit Service 8a4b7a
Packit Service 8a4b7a
    @mock.patch("common.CONFIG_STORE.get_config", new=get_config)
Packit Service 8a4b7a
    @mock.patch("common.PQOS_API.check_core", mock.MagicMock(return_value=True))
Packit Service 8a4b7a
    @mock.patch("pid_ops.is_pid_valid", mock.MagicMock(return_value=True))
Packit Service 8a4b7a
    @mock.patch("power.validate_power_profiles", mock.MagicMock(return_value=True))
Packit Service 8a4b7a
    @pytest.mark.parametrize("app_config", [
Packit Service 8a4b7a
        {"cores":[7,9]},                                                                # cores only
Packit Service 8a4b7a
        {"pool_id": 2, "name": "hello", "cores": [2], "pids": [1], "unknown": [7,9]}    # unknown
Packit Service 8a4b7a
    ])
Packit Service 8a4b7a
    def test_post_badrequest(self, app_config):
Packit Service 8a4b7a
        with mock.patch('common.CONFIG_STORE.set_config') as func_mock:
Packit Service 8a4b7a
            response = REST.post("/apps", app_config)
Packit Service 8a4b7a
            func_mock.assert_not_called()
Packit Service 8a4b7a
Packit Service 8a4b7a
        assert response.status_code == 400
Packit Service 8a4b7a
Packit Service 8a4b7a
    @mock.patch("common.CONFIG_STORE.get_config", new=get_config)
Packit Service 8a4b7a
    @mock.patch("common.PQOS_API.check_core", mock.MagicMock(return_value=False))
Packit Service 8a4b7a
    @mock.patch("pid_ops.is_pid_valid", mock.MagicMock(return_value=True))
Packit Service 8a4b7a
    @mock.patch("power.validate_power_profiles", mock.MagicMock(return_value=True))
Packit Service 8a4b7a
    @pytest.mark.parametrize("app_config", [
Packit Service 8a4b7a
        {"pool_id": 2, "name":"hello", "cores":2, "pids":[1]},                          # invalid core
Packit Service 8a4b7a
        {"pool_id": 2, "name":"hello", "cores":[-9], "pids":[1]},                       # invalid core
Packit Service 8a4b7a
        {"pool_id": 2, "name": "hello", "cores": [22], "pids": [1]}                     # core does not match pool id
Packit Service 8a4b7a
    ])
Packit Service 8a4b7a
    def test_post_invalid_core(self, app_config):
Packit Service 8a4b7a
        with mock.patch('common.CONFIG_STORE.set_config') as func_mock:
Packit Service 8a4b7a
            response = REST.post("/apps", app_config)
Packit Service 8a4b7a
            func_mock.assert_not_called()
Packit Service 8a4b7a
Packit Service 8a4b7a
        assert response.status_code == 400
Packit Service 8a4b7a
Packit Service 8a4b7a
    @mock.patch("common.CONFIG_STORE.get_config", new=get_config)
Packit Service 8a4b7a
    @mock.patch("common.PQOS_API.check_core", mock.MagicMock(return_value=True))
Packit Service 8a4b7a
    @mock.patch("pid_ops.is_pid_valid", mock.MagicMock(return_value=False))
Packit Service 8a4b7a
    @mock.patch("power.validate_power_profiles", mock.MagicMock(return_value=True))
Packit Service 8a4b7a
    @pytest.mark.parametrize("app_config", [
Packit Service 8a4b7a
        {"pool_id": 2, "name":"hello", "cores":[2], "pids":[199099]},                  # invalid PID
Packit Service 8a4b7a
        {"pool_id": 2, "pids": 1},                                                     # invalid "pids" format
Packit Service 8a4b7a
        {"pool_id": 2, "pids": [-1]},                                                  # invalid PID
Packit Service 8a4b7a
    ])
Packit Service 8a4b7a
    def test_post_invalid_pid(self, app_config):
Packit Service 8a4b7a
        with mock.patch('common.CONFIG_STORE.set_config') as func_mock:
Packit Service 8a4b7a
            response = REST.post("/apps", app_config)
Packit Service 8a4b7a
            func_mock.assert_not_called()
Packit Service 8a4b7a
Packit Service 8a4b7a
        assert response.status_code == 400
Packit Service 8a4b7a
Packit Service 8a4b7a
    @mock.patch("common.CONFIG_STORE.get_config", mock.MagicMock(return_value=CONFIG_EMPTY))
Packit Service 8a4b7a
    def test_post_empty_config(self):
Packit Service 8a4b7a
        with mock.patch('common.CONFIG_STORE.set_config') as func_mock:
Packit Service 8a4b7a
            response = REST.post("/apps", {"pool_id": 2, "name":"hello", "cores":[50], "pids":[1]})
Packit Service 8a4b7a
            func_mock.assert_not_called()
Packit Service 8a4b7a
Packit Service 8a4b7a
        assert response.status_code == 404
Packit Service 8a4b7a
Packit Service 8a4b7a
Packit Service 8a4b7a
class TestApp_2:
Packit Service 8a4b7a
    @mock.patch("common.CONFIG_STORE.get_config", new=get_config)
Packit Service 8a4b7a
    def test_get(self):
Packit Service 8a4b7a
        response = REST.get("/apps/2")
Packit Service 8a4b7a
        data = json.loads(response.data.decode('utf-8'))
Packit Service 8a4b7a
Packit Service 8a4b7a
        assert response.status_code == 200
Packit Service 8a4b7a
Packit Service 8a4b7a
        # validate get all pools response schema
Packit Service 8a4b7a
        schema, resolver = load_json_schema('get_app_response.json')
Packit Service 8a4b7a
        validate(data, schema, resolver=resolver)
Packit Service 8a4b7a
Packit Service 8a4b7a
        # assert 1 app is returned
Packit Service 8a4b7a
        # structure, types and required fields are validated using schema
Packit Service 8a4b7a
        assert data['id'] == 2
Packit Service 8a4b7a
Packit Service 8a4b7a
    @mock.patch("common.CONFIG_STORE.get_config", mock.MagicMock(return_value=CONFIG_EMPTY))
Packit Service 8a4b7a
    def test_get_empty(self):
Packit Service 8a4b7a
        response = REST.get("/apps/2")
Packit Service 8a4b7a
        data = json.loads(response.data.decode('utf-8'))
Packit Service 8a4b7a
Packit Service 8a4b7a
        # assert 0 apps are returned
Packit Service 8a4b7a
        assert response.status_code == 404
Packit Service 8a4b7a
        assert "No apps in config" in data["message"]
Packit Service 8a4b7a
Packit Service 8a4b7a
Packit Service 8a4b7a
    @mock.patch("common.CONFIG_STORE.get_config", new=get_config)
Packit Service 8a4b7a
    def test_delete_invalid_id(self):
Packit Service 8a4b7a
        with mock.patch('common.CONFIG_STORE.set_config') as func_mock:
Packit Service 8a4b7a
            response = REST.delete("/apps/10")
Packit Service 8a4b7a
            func_mock.assert_not_called()
Packit Service 8a4b7a
        data = json.loads(response.data.decode('utf-8'))
Packit Service 8a4b7a
Packit Service 8a4b7a
        # assert 0 apps are returned
Packit Service 8a4b7a
        assert response.status_code == 404
Packit Service 8a4b7a
        assert "APP 10 not found in config" in data["message"]
Packit Service 8a4b7a
Packit Service 8a4b7a
Packit Service 8a4b7a
    @mock.patch("common.CONFIG_STORE.get_config", new=get_config)
Packit Service 8a4b7a
    def test_delete(self):
Packit Service 8a4b7a
        def set_config(data):
Packit Service 8a4b7a
            for app in data['apps']:
Packit Service 8a4b7a
                assert app['id'] != 2
Packit Service 8a4b7a
            for pool in data['pools']:
Packit Service 8a4b7a
                assert ('apps' not in pool) or (2 not in pool['apps'])
Packit Service 8a4b7a
Packit Service 8a4b7a
        with mock.patch('common.CONFIG_STORE.set_config', side_effect=set_config) as func_mock:
Packit Service 8a4b7a
            response = REST.delete("/apps/2")
Packit Service 8a4b7a
            func_mock.assert_called_once()
Packit Service 8a4b7a
Packit Service 8a4b7a
        assert response.status_code == 200
Packit Service 8a4b7a
Packit Service 8a4b7a
Packit Service 8a4b7a
    @mock.patch("common.CONFIG_STORE.get_config", mock.MagicMock(return_value=CONFIG_EMPTY))
Packit Service 8a4b7a
    def test_delete_empty_config(self):
Packit Service 8a4b7a
        with mock.patch('common.CONFIG_STORE.set_config') as func_mock:
Packit Service 8a4b7a
            response = REST.delete("/apps/2")
Packit Service 8a4b7a
            func_mock.assert_not_called()
Packit Service 8a4b7a
Packit Service 8a4b7a
        assert response.status_code == 404
Packit Service 8a4b7a
Packit Service 8a4b7a
Packit Service 8a4b7a
    @mock.patch("common.CONFIG_STORE.get_config", new=get_config)
Packit Service 8a4b7a
    @mock.patch("common.PQOS_API.check_core", mock.MagicMock(return_value=True))
Packit Service 8a4b7a
    @mock.patch("pid_ops.is_pid_valid", mock.MagicMock(return_value=True))
Packit Service 8a4b7a
    @mock.patch("caps.cat_supported", mock.MagicMock(return_value=True))
Packit Service 8a4b7a
    @mock.patch("caps.mba_supported", mock.MagicMock(return_value=True))
Packit Service 8a4b7a
    @mock.patch("power.validate_power_profiles", mock.MagicMock(return_value=True))
Packit Service 8a4b7a
    def test_put_pool(self):
Packit Service 8a4b7a
        def set_config(data):
Packit Service 8a4b7a
            for pool in data['pools']:
Packit Service 8a4b7a
                if pool['id'] == 2:
Packit Service 8a4b7a
                    assert 2 in pool['apps']
Packit Service 8a4b7a
                else:
Packit Service 8a4b7a
                    assert ('apps' not in pool) or (2 not in pool['apps'])
Packit Service 8a4b7a
Packit Service 8a4b7a
        with mock.patch('common.CONFIG_STORE.set_config', side_effect=set_config) as func_mock:
Packit Service 8a4b7a
            response = REST.put("/apps/2", {"pool_id": 2})
Packit Service 8a4b7a
            func_mock.assert_called_once()
Packit Service 8a4b7a
Packit Service 8a4b7a
        assert response.status_code == 200
Packit Service 8a4b7a
Packit Service 8a4b7a
Packit Service 8a4b7a
    @mock.patch("common.CONFIG_STORE.get_config", new=get_config)
Packit Service 8a4b7a
    @mock.patch("common.PQOS_API.check_core", mock.MagicMock(return_value=True))
Packit Service 8a4b7a
    @mock.patch("pid_ops.is_pid_valid", mock.MagicMock(return_value=True))
Packit Service 8a4b7a
    @mock.patch("caps.cat_supported", mock.MagicMock(return_value=True))
Packit Service 8a4b7a
    @mock.patch("caps.mba_supported", mock.MagicMock(return_value=True))
Packit Service 8a4b7a
    @mock.patch("power.validate_power_profiles", mock.MagicMock(return_value=True))
Packit Service 8a4b7a
    def test_put_cores(self):
Packit Service 8a4b7a
        def set_config(data):
Packit Service 8a4b7a
            for app in data['apps']:
Packit Service 8a4b7a
                if app['id'] == 2:
Packit Service 8a4b7a
                    assert app['cores'] == [3]
Packit Service 8a4b7a
Packit Service 8a4b7a
        with mock.patch('common.CONFIG_STORE.set_config', side_effect=set_config) as func_mock:
Packit Service 8a4b7a
            response = REST.put("/apps/2", {"pool_id": 2, "cores": [3]})
Packit Service 8a4b7a
            func_mock.assert_called_once()
Packit Service 8a4b7a
Packit Service 8a4b7a
        assert response.status_code == 200
Packit Service 8a4b7a
Packit Service 8a4b7a
Packit Service 8a4b7a
    @mock.patch("common.CONFIG_STORE.get_config", new=get_config)
Packit Service 8a4b7a
    @mock.patch("common.PQOS_API.check_core", mock.MagicMock(return_value=True))
Packit Service 8a4b7a
    @mock.patch("pid_ops.is_pid_valid", mock.MagicMock(return_value=True))
Packit Service 8a4b7a
    def test_put_invalid_pool(self):
Packit Service 8a4b7a
        with mock.patch('common.CONFIG_STORE.set_config') as func_mock:
Packit Service 8a4b7a
            response = REST.put("/apps/2", {"pool_id": 20})
Packit Service 8a4b7a
            func_mock.assert_not_called()
Packit Service 8a4b7a
Packit Service 8a4b7a
        assert response.status_code == 400
Packit Service 8a4b7a
Packit Service 8a4b7a
Packit Service 8a4b7a
    @mock.patch("common.CONFIG_STORE.get_config", new=get_config)
Packit Service 8a4b7a
    @mock.patch("common.PQOS_API.check_core", mock.MagicMock(return_value=True))
Packit Service 8a4b7a
    @mock.patch("pid_ops.is_pid_valid", mock.MagicMock(return_value=True))
Packit Service 8a4b7a
    def test_put_invalid_app(self):
Packit Service 8a4b7a
        with mock.patch('common.CONFIG_STORE.set_config') as func_mock:
Packit Service 8a4b7a
            response = REST.put("/apps/20", {"pool_id": 2})
Packit Service 8a4b7a
            func_mock.assert_not_called()
Packit Service 8a4b7a
Packit Service 8a4b7a
        assert response.status_code == 404
Packit Service 8a4b7a
Packit Service 8a4b7a
Packit Service 8a4b7a
    @mock.patch("common.CONFIG_STORE.get_config", new=get_config)
Packit Service 8a4b7a
    @mock.patch("common.PQOS_API.check_core", mock.MagicMock(return_value=True))
Packit Service 8a4b7a
    @mock.patch("pid_ops.is_pid_valid", mock.MagicMock(return_value=True))
Packit Service 8a4b7a
    def test_put_invalid(self):
Packit Service 8a4b7a
        with mock.patch('common.CONFIG_STORE.set_config') as func_mock:
Packit Service 8a4b7a
            response = REST.put("/apps/2", {"invalid": 20})
Packit Service 8a4b7a
            func_mock.assert_not_called()
Packit Service 8a4b7a
Packit Service 8a4b7a
        assert response.status_code == 400
Packit Service 8a4b7a
Packit Service 8a4b7a
    @mock.patch("common.CONFIG_STORE.get_config", mock.MagicMock(return_value=CONFIG_EMPTY))
Packit Service 8a4b7a
    def test_put_empty_config(self):
Packit Service 8a4b7a
        with mock.patch('common.CONFIG_STORE.set_config') as func_mock:
Packit Service 8a4b7a
            response = REST.put("/apps/20", {"pool_id": 2})
Packit Service 8a4b7a
            func_mock.assert_not_called()
Packit Service 8a4b7a
Packit Service 8a4b7a
        assert response.status_code == 404