<commit_before># -*- coding: utf-8 -*-

# FOGLAMP_BEGIN
# See: http://foglamp.readthedocs.io/
# FOGLAMP_END

import pytest
import asyncio
from unittest.mock import patch, call, MagicMock
from foglamp.common import logger
from foglamp.common.storage_client.storage_client import ReadingsStorageClient, StorageClient
from foglamp.common.statistics import Statistics
from foglamp.tasks.purge.purge import Purge
from foglamp.common.process import FoglampProcess
from foglamp.common.configuration_manager import ConfigurationManager
from foglamp.common.audit_logger import AuditLogger
from foglamp.common.storage_client.exceptions import *

__author__ = "Vaibhav Singhal"
__copyright__ = "Copyright (c) 2017 OSIsoft, LLC"
__license__ = "Apache 2.0"
__version__ = "${VERSION}"

@pytest.allure.feature("unit")
@pytest.allure.story("tasks", "purge")
class TestPurge:
    """Test the units of purge.py"""

    def test_init(self, event_loop):
        """Test that creating an instance of Purge calls init of FoglampProcess and creates loggers"""
        mockStorageClient = MagicMock(spec=StorageClient)
        mockAuditLogger = AuditLogger(mockStorageClient)
        with patch.object(FoglampProcess, "__init__") as mock_process:
            with patch.object(logger, "setup") as log:
                with patch.object(mockAuditLogger, "__init__", return_value=None):
                    p = Purge(loop=event_loop)
                assert isinstance(p, Purge)
                assert isinstance(p._audit, AuditLogger)
            log.assert_called_once_with("Data Purge")
        mock_process.assert_called_once_with()

    def test_write_statistics(self, event_loop):
        """Test that write_statistics calls update statistics with defined keys and value increments"""

        @asyncio.coroutine
        def mock_s_update():
            return ""

        mockStorageClient = MagicMock(spec=StorageClient)
        mockAuditLogger = AuditLogger(mockStorageClient)
        with patch.object(FoglampProcess, '__init__'):
            with patch.object(Statistics, 'update', return_value=mock_s_update()) as mock_stats_update:
                with patch.object(mockAuditLogger, "__init__", return_value=None):
                    p = Purge(loop=event_loop)
                    p._storage = mockStorageClient
                    p.write_statistics(1, 2)
                    mock_stats_update.assert_has_calls([call('PURGED', 1), call('UNSNPURGED', 2)])

    def test_set_configuration(self, event_loop):
        """Test that purge's set_configuration returns configuration item with key 'PURGE_READ' """

        @asyncio.coroutine
        def mock_cm_return():
            return ""

        mockStorageClient = MagicMock(spec=StorageClient)
        mockAuditLogger = AuditLogger(mockStorageClient)
        with patch.object(FoglampProcess, '__init__'):
            with patch.object(mockAuditLogger, "__init__", return_value=None):
                p = Purge(loop=event_loop)
                p._storage = MagicMock(spec=StorageClient)
                mock_cm = ConfigurationManager(p._storage)
                with patch.object(mock_cm, 'create_category', return_value=mock_cm_return()) as mock_create_cat:
                    with patch.object(mock_cm, 'get_category_all_items', return_value=mock_cm_return()) \
                            as mock_get_cat:
                        p.set_configuration()
                        mock_get_cat.assert_called_once_with('PURGE_READ')
                    args, kwargs = mock_create_cat.call_args
                    assert len(args) == 3
                    assert args[0] == 'PURGE_READ'

    @pytest.fixture()
    def store_purge(self, **kwargs):
        if kwargs.get('age') == '-1' or kwargs.get('size') == '-1':
            raise StorageServerError(400, "Bla", "Some Error")
        return {"readings": 10, "removed": 1, "unsentPurged": 2, "unsentRetained": 7}

    config = {"purgeAgeSize": {"retainUnsent": {"value": "False"}, "age": {"value": "72"}, "size": {"value": "20"}},
              "purgeAge": {"retainUnsent": {"value": "False"}, "age": {"value": "72"}, "size": {"value": "0"}},
              "purgeSize": {"retainUnsent": {"value": "False"}, "age": {"value": "0"}, "size": {"value": "100"}},
              "retainAgeSize": {"retainUnsent": {"value": "True"}, "age": {"value": "72"}, "size": {"value": "20"}},
              "retainAge": {"retainUnsent": {"value": "True"}, "age": {"value": "72"}, "size": {"value": "0"}},
              "retainSize": {"retainUnsent": {"value": "True"}, "age": {"value": "0"}, "size": {"value": "100"}}}

    @pytest.mark.parametrize("conf, expected_return, expected_calls", [
        (config["purgeAgeSize"], (2, 4), {'sent_id': 0, 'size': '20', 'flag': 'purge'}),
        (config["purgeAge"], (1, 2), {'sent_id': 0, 'age': '72', 'flag': 'purge'}),
        (config["purgeSize"], (1, 2), {'sent_id': 0, 'size': '100', 'flag': 'purge'}),
        (config["retainAgeSize"], (2, 4), {'sent_id': 0, 'size': '20', 'flag': 'retain'}),
        (config["retainAge"], (1, 2), {'sent_id': 0, 'age': '72', 'flag': 'retain'}),
        (config["retainSize"], (1, 2), {'sent_id': 0, 'size': '100', 'flag': 'retain'})
    ])
    def test_purge_data(self, event_loop, conf, expected_return, expected_calls):
        """Test that purge_data calls Storage's purge with defined configuration"""

        @asyncio.coroutine
        def mock_audit_info():
            return ""

        mockStorageClient = MagicMock(spec=StorageClient)
        mockAuditLogger = AuditLogger(mockStorageClient)

        with patch.object(FoglampProcess, '__init__'):
            with patch.object(mockAuditLogger, "__init__", return_value=None):
                p = Purge(loop=event_loop)
                p._logger = logger
                p._logger.info = MagicMock()
                p._logger.error = MagicMock()
                p._storage = MagicMock(spec=StorageClient)
                p._readings_storage = MagicMock(spec=ReadingsStorageClient)
                audit = p._audit
                with patch.object(p._readings_storage, 'purge', side_effect=self.store_purge) as mock_storage_purge:
                    with patch.object(audit, 'information', return_value=mock_audit_info()) as audit_info:
                        # Test the positive case when all if conditions in purge_data pass
                        assert expected_return == p.purge_data(conf)
                        assert audit_info.called
                        args, kwargs = mock_storage_purge.call_args
                        assert kwargs == expected_calls

    @pytest.mark.parametrize("conf, expected_return", [
        ({"retainUnsent": {"value": "False"}, "age": {"value": "0"}, "size": {"value": "0"}}, (0, 0)),
        ({"retainUnsent": {"value": "True"}, "age": {"value": "0"}, "size": {"value": "0"}}, (0, 0))
    ])
    def test_purge_data_no_data_purged(self, event_loop, conf, expected_return):
        """Test that purge_data logs message when no data was purged"""

        @asyncio.coroutine
        def mock_audit_info():
            return ""

        mockStorageClient = MagicMock(spec=StorageClient)
        mockAuditLogger = AuditLogger(mockStorageClient)

        with patch.object(FoglampProcess, '__init__'):
            with patch.object(mockAuditLogger, "__init__", return_value=None):
                p = Purge(loop=event_loop)
                p._logger = logger
                p._logger.info = MagicMock()
                p._logger.error = MagicMock()
                p._storage = MagicMock(spec=StorageClient)
                p._readings_storage = MagicMock(spec=ReadingsStorageClient)
                audit = p._audit
                with patch.object(p._readings_storage, 'purge', side_effect=self.store_purge):
                    with patch.object(audit, 'information', return_value=mock_audit_info()):
                        assert expected_return == p.purge_data(conf)
                        p._logger.info.assert_called_once_with("No rows purged")

    @pytest.mark.parametrize("conf, expected_return", [
        ({"retainUnsent": {"value": "True"}, "age": {"value": "-1"}, "size": {"value": "-1"}}, (0, 0))
    ])
    def test_purge_error_storage_response(self, event_loop, conf, expected_return):
        """Test that purge_data logs error when storage purge returns an error response"""

        @asyncio.coroutine
        def mock_audit_info():
            return ""

        mockStorageClient = MagicMock(spec=StorageClient)
        mockAuditLogger = AuditLogger(mockStorageClient)

        with patch.object(FoglampProcess, '__init__'):
            with patch.object(mockAuditLogger, "__init__", return_value=None):
                p = Purge(loop=event_loop)
                p._logger = logger
                p._logger.info = MagicMock()
                p._logger.error = MagicMock()
                p._storage = MagicMock(spec=StorageClient)
                p._readings_storage = MagicMock(spec=ReadingsStorageClient)
                audit = p._audit
                with patch.object(p._readings_storage, 'purge', side_effect=self.store_purge):
                    with patch.object(audit, 'information', return_value=mock_audit_info()):
                        assert expected_return == p.purge_data(conf)

    @pytest.mark.parametrize("conf, expected_error_key",
                             [({"retainUnsent": {"value": "True"}, "age": {"value": "bla"}, "size": {"value": "0"}},
                               "age"),
                              ({"retainUnsent": {"value": "True"}, "age": {"value": "0"}, "size": {"value": "bla"}},
                               "size")])
    def test_purge_data_invalid_conf(self, event_loop, conf, expected_error_key):
        """Test that purge_data raises exception when called with invalid configuration"""

        @asyncio.coroutine
        def mock_audit_info():
            return ""

        mockStorageClient = MagicMock(spec=StorageClient)
        mockAuditLogger = AuditLogger(mockStorageClient)

        with patch.object(FoglampProcess, '__init__'):
            with patch.object(mockAuditLogger, "__init__", return_value=None):
                p = Purge(loop=event_loop)
                p._logger = logger
                p._logger.info = MagicMock()
                p._logger.error = MagicMock()
                p._storage = MagicMock(spec=StorageClient)
                p._readings_storage = MagicMock(spec=ReadingsStorageClient)
                audit = p._audit
                with patch.object(p._readings_storage, 'purge', side_effect=self.store_purge):
                    with patch.object(audit, 'information', return_value=mock_audit_info()):
                        # Test the code block when purge failed because of invalid configuration
                        p.purge_data(conf)
                        p._logger.error.assert_called_with('Configuration item {} bla should be integer!'.
                                                           format(expected_error_key))

    def test_run(self, event_loop):
        """Test that run calls all units of purge process"""
        @asyncio.coroutine
        def mock_audit_info():
            return ""

        mockStorageClient = MagicMock(spec=StorageClient)
        mockAuditLogger = AuditLogger(mockStorageClient)

        with patch.object(FoglampProcess, '__init__'):
            with patch.object(mockAuditLogger, "__init__", return_value=None):
                p = Purge(loop=event_loop)
                config = "Some config"
                p._logger.exception = MagicMock()
                with patch.object(p, 'set_configuration', return_value=config) as mock_set_config:
                    with patch.object(p, 'purge_data', return_value=(1, 2)) as mock_purge_data:
                        with patch.object(p, 'write_statistics') as mock_write_stats:
                            p.run()
                # Test the positive case when no error in try block
                mock_set_config.assert_called_once_with()
                mock_purge_data.assert_called_once_with(config)
                mock_write_stats.assert_called_once_with(1, 2)

    def test_run_exception(self, event_loop):
        """Test that run calls all units of purge process and checks the exception handling"""
        @asyncio.coroutine
        def mock_audit_info():
            return ""

        mockStorageClient = MagicMock(spec=StorageClient)
        mockAuditLogger = AuditLogger(mockStorageClient)

        with patch.object(FoglampProcess, '__init__'):
            with patch.object(mockAuditLogger, "__init__", return_value=None):
                p = Purge(loop=event_loop)
                config = "Some config"
                p._logger.exception = MagicMock()
                with patch.object(p, 'set_configuration', return_value=config):
                    with patch.object(p, 'purge_data', return_value=Exception()):
                        with patch.object(p, 'write_statistics'):
                            p.run()
                # Test the negative case when function purge_data raise some exception
                p._logger.exception.assert_called_once_with("'Exception' object is not iterable")
<commit_msg>Test fixed with use of async storage client in statistics<commit_after># -*- coding: utf-8 -*-

# FOGLAMP_BEGIN
# See: http://foglamp.readthedocs.io/
# FOGLAMP_END

import pytest
import asyncio
from unittest.mock import patch, call, MagicMock
from foglamp.common import logger
from foglamp.common.storage_client.storage_client import ReadingsStorageClient, StorageClient, StorageClientAsync
from foglamp.common.statistics import Statistics
from foglamp.tasks.purge.purge import Purge
from foglamp.common.process import FoglampProcess
from foglamp.common.configuration_manager import ConfigurationManager
from foglamp.common.audit_logger import AuditLogger
from foglamp.common.storage_client.exceptions import *

__author__ = "Vaibhav Singhal"
__copyright__ = "Copyright (c) 2017 OSIsoft, LLC"
__license__ = "Apache 2.0"
__version__ = "${VERSION}"

@pytest.allure.feature("unit")
@pytest.allure.story("tasks", "purge")
class TestPurge:
    """Test the units of purge.py"""

    def test_init(self, event_loop):
        """Test that creating an instance of Purge calls init of FoglampProcess and creates loggers"""
        mockStorageClient = MagicMock(spec=StorageClient)
        mockAuditLogger = AuditLogger(mockStorageClient)
        with patch.object(FoglampProcess, "__init__") as mock_process:
            with patch.object(logger, "setup") as log:
                with patch.object(mockAuditLogger, "__init__", return_value=None):
                    p = Purge(loop=event_loop)
                assert isinstance(p, Purge)
                assert isinstance(p._audit, AuditLogger)
            log.assert_called_once_with("Data Purge")
        mock_process.assert_called_once_with()

    def test_write_statistics(self, event_loop):
        """Test that write_statistics calls update statistics with defined keys and value increments"""

        @asyncio.coroutine
        def mock_s_update():
            return ""

        mockStorageClient = MagicMock(spec=StorageClient)
        mockStorageClientAsync = MagicMock(spec=StorageClientAsync)
        mockAuditLogger = AuditLogger(mockStorageClient)
        with patch.object(FoglampProcess, '__init__'):
            with patch.object(Statistics, '_load_keys', return_value=mock_s_update()):
                with patch.object(Statistics, 'update', return_value=mock_s_update()) as mock_stats_update:
                    with patch.object(mockAuditLogger, "__init__", return_value=None):
                        p = Purge(loop=event_loop)
                        p._storage_async = mockStorageClientAsync
                        p.write_statistics(1, 2)
                        mock_stats_update.assert_has_calls([call('PURGED', 1), call('UNSNPURGED', 2)])

    def test_set_configuration(self, event_loop):
        """Test that purge's set_configuration returns configuration item with key 'PURGE_READ' """

        @asyncio.coroutine
        def mock_cm_return():
            return ""

        mockStorageClient = MagicMock(spec=StorageClient)
        mockAuditLogger = AuditLogger(mockStorageClient)
        with patch.object(FoglampProcess, '__init__'):
            with patch.object(mockAuditLogger, "__init__", return_value=None):
                p = Purge(loop=event_loop)
                p._storage = MagicMock(spec=StorageClient)
                mock_cm = ConfigurationManager(p._storage)
                with patch.object(mock_cm, 'create_category', return_value=mock_cm_return()) as mock_create_cat:
                    with patch.object(mock_cm, 'get_category_all_items', return_value=mock_cm_return()) \
                            as mock_get_cat:
                        p.set_configuration()
                        mock_get_cat.assert_called_once_with('PURGE_READ')
                    args, kwargs = mock_create_cat.call_args
                    assert len(args) == 3
                    assert args[0] == 'PURGE_READ'

    @pytest.fixture()
    def store_purge(self, **kwargs):
        if kwargs.get('age') == '-1' or kwargs.get('size') == '-1':
            raise StorageServerError(400, "Bla", "Some Error")
        return {"readings": 10, "removed": 1, "unsentPurged": 2, "unsentRetained": 7}

    config = {"purgeAgeSize": {"retainUnsent": {"value": "False"}, "age": {"value": "72"}, "size": {"value": "20"}},
              "purgeAge": {"retainUnsent": {"value": "False"}, "age": {"value": "72"}, "size": {"value": "0"}},
              "purgeSize": {"retainUnsent": {"value": "False"}, "age": {"value": "0"}, "size": {"value": "100"}},
              "retainAgeSize": {"retainUnsent": {"value": "True"}, "age": {"value": "72"}, "size": {"value": "20"}},
              "retainAge": {"retainUnsent": {"value": "True"}, "age": {"value": "72"}, "size": {"value": "0"}},
              "retainSize": {"retainUnsent": {"value": "True"}, "age": {"value": "0"}, "size": {"value": "100"}}}

    @pytest.mark.parametrize("conf, expected_return, expected_calls", [
        (config["purgeAgeSize"], (2, 4), {'sent_id': 0, 'size': '20', 'flag': 'purge'}),
        (config["purgeAge"], (1, 2), {'sent_id': 0, 'age': '72', 'flag': 'purge'}),
        (config["purgeSize"], (1, 2), {'sent_id': 0, 'size': '100', 'flag': 'purge'}),
        (config["retainAgeSize"], (2, 4), {'sent_id': 0, 'size': '20', 'flag': 'retain'}),
        (config["retainAge"], (1, 2), {'sent_id': 0, 'age': '72', 'flag': 'retain'}),
        (config["retainSize"], (1, 2), {'sent_id': 0, 'size': '100', 'flag': 'retain'})
    ])
    def test_purge_data(self, event_loop, conf, expected_return, expected_calls):
        """Test that purge_data calls Storage's purge with defined configuration"""

        @asyncio.coroutine
        def mock_audit_info():
            return ""

        mockStorageClient = MagicMock(spec=StorageClient)
        mockAuditLogger = AuditLogger(mockStorageClient)

        with patch.object(FoglampProcess, '__init__'):
            with patch.object(mockAuditLogger, "__init__", return_value=None):
                p = Purge(loop=event_loop)
                p._logger = logger
                p._logger.info = MagicMock()
                p._logger.error = MagicMock()
                p._storage = MagicMock(spec=StorageClient)
                p._readings_storage = MagicMock(spec=ReadingsStorageClient)
                audit = p._audit
                with patch.object(p._readings_storage, 'purge', side_effect=self.store_purge) as mock_storage_purge:
                    with patch.object(audit, 'information', return_value=mock_audit_info()) as audit_info:
                        # Test the positive case when all if conditions in purge_data pass
                        assert expected_return == p.purge_data(conf)
                        assert audit_info.called
                        args, kwargs = mock_storage_purge.call_args
                        assert kwargs == expected_calls

    @pytest.mark.parametrize("conf, expected_return", [
        ({"retainUnsent": {"value": "False"}, "age": {"value": "0"}, "size": {"value": "0"}}, (0, 0)),
        ({"retainUnsent": {"value": "True"}, "age": {"value": "0"}, "size": {"value": "0"}}, (0, 0))
    ])
    def test_purge_data_no_data_purged(self, event_loop, conf, expected_return):
        """Test that purge_data logs message when no data was purged"""

        @asyncio.coroutine
        def mock_audit_info():
            return ""

        mockStorageClient = MagicMock(spec=StorageClient)
        mockAuditLogger = AuditLogger(mockStorageClient)

        with patch.object(FoglampProcess, '__init__'):
            with patch.object(mockAuditLogger, "__init__", return_value=None):
                p = Purge(loop=event_loop)
                p._logger = logger
                p._logger.info = MagicMock()
                p._logger.error = MagicMock()
                p._storage = MagicMock(spec=StorageClient)
                p._readings_storage = MagicMock(spec=ReadingsStorageClient)
                audit = p._audit
                with patch.object(p._readings_storage, 'purge', side_effect=self.store_purge):
                    with patch.object(audit, 'information', return_value=mock_audit_info()):
                        assert expected_return == p.purge_data(conf)
                        p._logger.info.assert_called_once_with("No rows purged")

    @pytest.mark.parametrize("conf, expected_return", [
        ({"retainUnsent": {"value": "True"}, "age": {"value": "-1"}, "size": {"value": "-1"}}, (0, 0))
    ])
    def test_purge_error_storage_response(self, event_loop, conf, expected_return):
        """Test that purge_data logs error when storage purge returns an error response"""

        @asyncio.coroutine
        def mock_audit_info():
            return ""

        mockStorageClient = MagicMock(spec=StorageClient)
        mockAuditLogger = AuditLogger(mockStorageClient)

        with patch.object(FoglampProcess, '__init__'):
            with patch.object(mockAuditLogger, "__init__", return_value=None):
                p = Purge(loop=event_loop)
                p._logger = logger
                p._logger.info = MagicMock()
                p._logger.error = MagicMock()
                p._storage = MagicMock(spec=StorageClient)
                p._readings_storage = MagicMock(spec=ReadingsStorageClient)
                audit = p._audit
                with patch.object(p._readings_storage, 'purge', side_effect=self.store_purge):
                    with patch.object(audit, 'information', return_value=mock_audit_info()):
                        assert expected_return == p.purge_data(conf)

    @pytest.mark.parametrize("conf, expected_error_key",
                             [({"retainUnsent": {"value": "True"}, "age": {"value": "bla"}, "size": {"value": "0"}},
                               "age"),
                              ({"retainUnsent": {"value": "True"}, "age": {"value": "0"}, "size": {"value": "bla"}},
                               "size")])
    def test_purge_data_invalid_conf(self, event_loop, conf, expected_error_key):
        """Test that purge_data raises exception when called with invalid configuration"""

        @asyncio.coroutine
        def mock_audit_info():
            return ""

        mockStorageClient = MagicMock(spec=StorageClient)
        mockAuditLogger = AuditLogger(mockStorageClient)

        with patch.object(FoglampProcess, '__init__'):
            with patch.object(mockAuditLogger, "__init__", return_value=None):
                p = Purge(loop=event_loop)
                p._logger = logger
                p._logger.info = MagicMock()
                p._logger.error = MagicMock()
                p._storage = MagicMock(spec=StorageClient)
                p._readings_storage = MagicMock(spec=ReadingsStorageClient)
                audit = p._audit
                with patch.object(p._readings_storage, 'purge', side_effect=self.store_purge):
                    with patch.object(audit, 'information', return_value=mock_audit_info()):
                        # Test the code block when purge failed because of invalid configuration
                        p.purge_data(conf)
                        p._logger.error.assert_called_with('Configuration item {} bla should be integer!'.
                                                           format(expected_error_key))

    def test_run(self, event_loop):
        """Test that run calls all units of purge process"""
        @asyncio.coroutine
        def mock_audit_info():
            return ""

        mockStorageClient = MagicMock(spec=StorageClient)
        mockAuditLogger = AuditLogger(mockStorageClient)

        with patch.object(FoglampProcess, '__init__'):
            with patch.object(mockAuditLogger, "__init__", return_value=None):
                p = Purge(loop=event_loop)
                config = "Some config"
                p._logger.exception = MagicMock()
                with patch.object(p, 'set_configuration', return_value=config) as mock_set_config:
                    with patch.object(p, 'purge_data', return_value=(1, 2)) as mock_purge_data:
                        with patch.object(p, 'write_statistics') as mock_write_stats:
                            p.run()
                # Test the positive case when no error in try block
                mock_set_config.assert_called_once_with()
                mock_purge_data.assert_called_once_with(config)
                mock_write_stats.assert_called_once_with(1, 2)

    def test_run_exception(self, event_loop):
        """Test that run calls all units of purge process and checks the exception handling"""
        @asyncio.coroutine
        def mock_audit_info():
            return ""

        mockStorageClient = MagicMock(spec=StorageClient)
        mockAuditLogger = AuditLogger(mockStorageClient)

        with patch.object(FoglampProcess, '__init__'):
            with patch.object(mockAuditLogger, "__init__", return_value=None):
                p = Purge(loop=event_loop)
                config = "Some config"
                p._logger.exception = MagicMock()
                with patch.object(p, 'set_configuration', return_value=config):
                    with patch.object(p, 'purge_data', return_value=Exception()):
                        with patch.object(p, 'write_statistics'):
                            p.run()
                # Test the negative case when function purge_data raise some exception
                p._logger.exception.assert_called_once_with("'Exception' object is not iterable")
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-

# FOGLAMP_BEGIN
# See: http://foglamp.readthedocs.io/
# FOGLAMP_END

import asyncio
from unittest.mock import patch, call
import pytest
import logging
from foglamp.common.storage_client.storage_client import StorageClient
from foglamp.common.statistics import Statistics
from foglamp.tasks.purge.purge import Purge
from foglamp.common.process import FoglampProcess

__author__ = "Vaibhav Singhal"
__copyright__ = "Copyright (c) 2017 OSIsoft, LLC"
__license__ = "Apache 2.0"
__version__ = "${VERSION}"

@pytest.allure.feature("unit")
@pytest.allure.story("tasks", "purge")
class TestPurge:
    """Test the units of purge.py"""

    def test_init(self):
        """Test that creating an instance of Purge calls init of FoglampProcess and creates logger"""
        with patch.object(FoglampProcess, "__init__") as fp:
            p = Purge()
            assert isinstance(p._logger, logging.Logger)
        fp.assert_called_once_with()

    def test_write_statistics(self):
        """Test that write_statistics calls update statistics with defined keys and value increments"""
        with patch.object(FoglampProcess, '__init__'):
            with patch.object(Statistics, '__init__', return_value=None):
                with patch.object(Statistics, 'update', return_value=asyncio.ensure_future(asyncio.sleep(0.1)))\
                        as mock_update:
                    p = Purge()
                    p.write_statistics(1, 2)
                    mock_update.assert_has_calls([call('PURGED', 1), call('UNSNPURGED', 2)])

    def test_insert_into_log(self):
        pass

    def test_set_configuration(self):
        pass

    def test_purge_data(self):
        pass

    def test_run(self):
        pass<commit_msg>Test added for purge_data unit<commit_after># -*- coding: utf-8 -*-

# FOGLAMP_BEGIN
# See: http://foglamp.readthedocs.io/
# FOGLAMP_END

import asyncio
from unittest.mock import patch, call, MagicMock
import pytest
import logging
from foglamp.common.storage_client.storage_client import ReadingsStorageClient, StorageClient
from foglamp.common.statistics import Statistics
from foglamp.tasks.purge.purge import Purge
from foglamp.common.process import FoglampProcess

__author__ = "Vaibhav Singhal"
__copyright__ = "Copyright (c) 2017 OSIsoft, LLC"
__license__ = "Apache 2.0"
__version__ = "${VERSION}"

@pytest.allure.feature("unit")
@pytest.allure.story("tasks", "purge")
class TestPurge:
    """Test the units of purge.py"""

    def test_init(self):
        """Test that creating an instance of Purge calls init of FoglampProcess and creates logger"""
        with patch.object(FoglampProcess, "__init__") as fp:
            p = Purge()
            assert isinstance(p._logger, logging.Logger)
        fp.assert_called_once_with()

    def test_write_statistics(self):
        """Test that write_statistics calls update statistics with defined keys and value increments"""
        with patch.object(FoglampProcess, '__init__'):
            with patch.object(Statistics, '__init__', return_value=None):
                with patch.object(Statistics, 'update', return_value=asyncio.ensure_future(asyncio.sleep(0.1)))\
                        as mock_update:
                    p = Purge()
                    p.write_statistics(1, 2)
                    mock_update.assert_has_calls([call('PURGED', 1), call('UNSNPURGED', 2)])

    def test_insert_into_log(self):
        # TODO: FOGL-701
        pass

    def test_set_configuration(self):
        pass

    config = [{"retainUnsent": {"value": "False"}, "age": {"value": "72"}, "size": {"value": "0"}},
              {"retainUnsent": {"value": "True"}, "age": {"value": "0"}, "size": {"value": "100"}}]

    @pytest.mark.parametrize("conf, flag", [
        (config[0], "purge"),
        (config[1], "retain")
    ])
    def test_purge_data(self, conf, flag):
        """Test that purge_data calls Storage's purge with defined values"""
        # TODO: FOGL-701 AuditLogger tests
        with patch.object(FoglampProcess, '__init__'):
            p = Purge()
            p._storage = MagicMock(spec=StorageClient)
            p._readings_storage = MagicMock(spec=ReadingsStorageClient)
            p._insert_into_log = MagicMock()
            with patch.object(p._readings_storage, 'purge') as mock_storage_purge:
                with patch.object(p, '_insert_into_log') as mock_insert:
                    p.purge_data(conf)
                assert mock_insert.called
            mock_storage_purge.assert_has_calls([call(age=conf["age"]["value"], flag=flag, sent_id=0)],
                                                [call(size=conf["size"]["value"], flag=flag, sent_id=0)])

    def test_run(self):
        pass
<|endoftext|>


<commit_before>"""Image info contains all well known system image files."""

load("//tools/android/emulated_devices:macro/image.bzl", "image_api", "new_image")
load("//tools/android/emulated_devices:macro/props.bzl", "new_props")

_IMG_TEMPLATE = (
    "@androidsdk//:emulator_images_%s"
)

_GOOGLE = "google"
_ANDROID = "android"
_WEAR = "wear"
_WEAR_TESTKEYS = "wear-testkeys"
_WEAR_LE = "wear-le"
_TV = "tv"
_AUTO = "auto"
_GO = "go"
_JASPER = "jasper"
_DAYDREAM = "daydream"
_AXON = "axon"

def _default_images(api_level, flavors, props = None):
    """Helper function to build standard images."""
    images = []
    for a in ["arm", "x86"]:
        for f in flavors:
            for compressed in (True, False):
                target = "%s_%s_%s" % (f, api_level, a)
                images.append(
                    new_image(
                        flavor = f,
                        api_level = api_level,
                        arch = a,
                        files = _IMG_TEMPLATE % target,
                        compressed = compressed,
                        props = props,
                    ),
                )
    return images

_NUM_CORES_PROP = "hw.cpu.ncore"

_ALL_IMAGES = (
    _default_images(10, [_GOOGLE, _ANDROID]) +
    _default_images(
        15,
        [_GOOGLE, _ANDROID],
        props = new_props(
            avd_properties = {
                _NUM_CORES_PROP: "1",  # b/73511483
            },
        ),
    ) +
    _default_images(16, [_GOOGLE, _ANDROID]) +
    _default_images(17, [_GOOGLE, _ANDROID]) +
    _default_images(18, [_GOOGLE, _ANDROID]) +
    _default_images(19, [_GOOGLE, _ANDROID]) +
    _default_images(20, [_WEAR]) +
    _default_images(21, [_GOOGLE, _ANDROID, _WEAR, _TV]) +
    _default_images(22, [_GOOGLE, _ANDROID, _WEAR, _TV]) +
    _default_images(23, [_GOOGLE, _ANDROID, _WEAR, _TV]) +
    _default_images(24, [_GOOGLE, _ANDROID, _WEAR, _TV, _JASPER]) +
    _default_images(25, [_GOOGLE, _ANDROID, _WEAR, _WEAR_LE, _WEAR_TESTKEYS, _AXON]) +
    _default_images(
        26,
        [_GOOGLE, _ANDROID, _WEAR, _WEAR_LE, _AUTO, _DAYDREAM, _TV],
    ) +
    _default_images(27, [_GOOGLE, _ANDROID, _GO, _AUTO, _DAYDREAM, _TV]) +
    _default_images(28, [_GOOGLE, _AUTO, _DAYDREAM])
)

def _api_to_images():
    a2i = {}
    for image in _ALL_IMAGES:
        api = image_api(image)
        images = a2i.get(api, [])
        images.append(image)
        a2i[api] = images
    return a2i

API_TO_IMAGES = _api_to_images()
<commit_msg>[]<commit_after>"""Image info contains all well known system image files."""

load("//tools/android/emulated_devices:macro/image.bzl", "image_api", "new_image")
load("//tools/android/emulated_devices:macro/props.bzl", "new_props")

_IMG_TEMPLATE = (
    "@androidsdk//:emulator_images_%s"
)

_GOOGLE = "google"
_ANDROID = "android"
_WEAR = "wear"
_WEAR_TESTKEYS = "wear-testkeys"
_WEAR_LE = "wear-le"
_TV = "tv"
_AUTO = "auto"
_GO = "go"
_JASPER = "jasper"
_DAYDREAM = "daydream"
_AXON = "axon"

def _default_images(api_level, flavors, props = None):
    """Helper function to build standard images."""
    images = []
    for a in ["arm", "x86"]:
        for f in flavors:
            for compressed in (True, False):
                target = "%s_%s_%s" % (f, api_level, a)
                images.append(
                    new_image(
                        flavor = f,
                        api_level = api_level,
                        arch = a,
                        files = _IMG_TEMPLATE % target,
                        compressed = compressed,
                        props = props,
                    ),
                )
    return images

_NUM_CORES_PROP = "hw.cpu.ncore"

_ALL_IMAGES = (
    _default_images(10, [_GOOGLE, _ANDROID]) +
    _default_images(
        15,
        [_GOOGLE, _ANDROID],
        props = new_props(
            avd_properties = {
                _NUM_CORES_PROP: "1",  # b/73511483
            },
        ),
    ) +
    _default_images(16, [_GOOGLE, _ANDROID]) +
    _default_images(17, [_GOOGLE, _ANDROID]) +
    _default_images(18, [_GOOGLE, _ANDROID]) +
    _default_images(19, [_GOOGLE, _ANDROID]) +
    _default_images(20, [_WEAR]) +
    _default_images(21, [_GOOGLE, _ANDROID, _WEAR, _TV]) +
    _default_images(22, [_GOOGLE, _ANDROID, _WEAR, _TV]) +
    _default_images(23, [_GOOGLE, _ANDROID, _WEAR, _TV]) +
    _default_images(24, [_GOOGLE, _ANDROID, _WEAR, _TV, _JASPER]) +
    _default_images(25, [_GOOGLE, _ANDROID, _WEAR, _WEAR_LE, _WEAR_TESTKEYS, _AXON]) +
    _default_images(
        26,
        [_GOOGLE, _ANDROID, _WEAR, _WEAR_LE, _AUTO, _DAYDREAM, _TV],
    ) +
    _default_images(27, [_GOOGLE, _ANDROID, _GO, _AUTO, _DAYDREAM, _TV, _JASPER]) +
    _default_images(28, [_GOOGLE, _AUTO, _DAYDREAM])
)

def _api_to_images():
    a2i = {}
    for image in _ALL_IMAGES:
        api = image_api(image)
        images = a2i.get(api, [])
        images.append(image)
        a2i[api] = images
    return a2i

API_TO_IMAGES = _api_to_images()
<|endoftext|>


<commit_before>import copy
import sys
import subprocess
from subprocess import PIPE
import requests

# Requests is built ontop of urllib3,
# here we prevent general request logging
import logging
logging.getLogger('urllib3').setLevel(logging.CRITICAL)

from pprint import pprint

class FrameworkTestType:
  '''Interface between a test type (json, query, plaintext, etc) and
  the rest of TFB. A test type defines a number of keys it expects
  to find in the benchmark_config.json, and this base class handles extracting
  those keys and injecting them into the test. For example, if
  benchmark_config.json contains a line `"spam" : "foobar"` and a subclasses X
  passes an argument list of ['spam'], then after parsing there will
  exist a member `X.spam = 'foobar'`.
  '''

  def __init__(self, name, requires_db=False, accept_header=None, args=[]):
    self.name = name
    self.requires_db = requires_db
    self.args = args
    self.out = sys.stdout
    self.err = sys.stderr
    if accept_header is None:
      self.accept_header = self.accept('json')
    else:
      self.accept_header = accept_header

    self.passed = None
    self.failed = None
    self.warned = None

  def accept(self, content_type):
    return {
      'json': 'application/json,text/html;q=0.9,application/xhtml+xml;q=0.9,application/xml;q=0.8,*/*;q=0.7',
      'html': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
      'plaintext': 'text/plain,text/html;q=0.9,application/xhtml+xml;q=0.9,application/xml;q=0.8,*/*;q=0.7'
    }[content_type]

  def setup_out_err(self, out, err):
    '''Sets up file-like objects for logging. Used in
    cases where it is hard just return the output. Any
    output sent to these file objects is also printed to
    the console

    NOTE: I detest this. It would be much better to use
    logging like it's intended
    '''
    self.out = out
    self.err = err

  def parse(self, test_keys):
    '''Takes the dict of key/value pairs describing a FrameworkTest
    and collects all variables needed by this FrameworkTestType

    Raises AttributeError if required keys are missing
    '''
    if all (arg in test_keys for arg in self.args):
      self.__dict__.update({ arg:test_keys[arg] for arg in self.args})
      return self
    else: # This is quite common - most tests don't support all types
      raise AttributeError("A %s requires the benchmark_config.json to contain %s"%(self.name,self.args))

  def request_headers_and_body(self, url):
    '''
    Downloads a URL and returns the HTTP response headers
    and body content as a tuple
    '''
    print "Accessing URL %s:" % url
    self.err.write("Accessing URL %s \n" % url)
    self.out.write("Accessing URL %s \n" % url)

    r = requests.get(url, timeout=15)
    try:
      r.raise_for_status() # Throws on non-200
      headers = r.headers
      body = r.content
      self.out.write(str(headers))
      self.out.write(body)

      b = 40
      print "  Response (trimmed to %d bytes): \"%s\"" % (b, body.strip()[:b])

      return headers, body
    except requests.HTTPError as err:
      self.err.write(err + '\n')
      return None, None

  def verify(self, base_url):
    '''Accesses URL used by this test type and checks the return
    values for correctness. Most test types run multiple checks,
    so this returns a list of results. Each result is a 3-tuple
    of (String result, String reason, String urlTested).

    - result : 'pass','warn','fail'
    - reason : Short human-readable reason if result was
        warn or fail. Please do not print the response as part of this,
        other parts of TFB will do that based upon the current logging
        settings if this method indicates a failure happened
    - urlTested: The exact URL that was queried

    Subclasses should make a best-effort attempt to report as many
    failures and warnings as they can to help users avoid needing
    to run TFB repeatedly while debugging
    '''
    # TODO make String result into an enum to enforce
    raise NotImplementedError("Subclasses must provide verify")

  def get_url(self):
    '''Returns the URL for this test, like '/json'''
    # This is a method because each test type uses a different key
    # for their URL so the base class can't know which arg is the URL
    raise NotImplementedError("Subclasses must provide verify")

  def copy(self):
    '''Returns a copy that can be safely modified. Use before calling
    parse'''
    return copy.copy(self)

<commit_msg>Include the `Accept` header when making the request<commit_after>import copy
import sys
import subprocess
from subprocess import PIPE
import requests

# Requests is built ontop of urllib3,
# here we prevent general request logging
import logging
logging.getLogger('urllib3').setLevel(logging.CRITICAL)

from pprint import pprint

class FrameworkTestType:
  '''Interface between a test type (json, query, plaintext, etc) and
  the rest of TFB. A test type defines a number of keys it expects
  to find in the benchmark_config.json, and this base class handles extracting
  those keys and injecting them into the test. For example, if
  benchmark_config.json contains a line `"spam" : "foobar"` and a subclasses X
  passes an argument list of ['spam'], then after parsing there will
  exist a member `X.spam = 'foobar'`.
  '''

  def __init__(self, name, requires_db=False, accept_header=None, args=[]):
    self.name = name
    self.requires_db = requires_db
    self.args = args
    self.out = sys.stdout
    self.err = sys.stderr
    if accept_header is None:
      self.accept_header = self.accept('json')
    else:
      self.accept_header = accept_header

    self.passed = None
    self.failed = None
    self.warned = None

  def accept(self, content_type):
    return {
      'json': 'application/json,text/html;q=0.9,application/xhtml+xml;q=0.9,application/xml;q=0.8,*/*;q=0.7',
      'html': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
      'plaintext': 'text/plain,text/html;q=0.9,application/xhtml+xml;q=0.9,application/xml;q=0.8,*/*;q=0.7'
    }[content_type]

  def setup_out_err(self, out, err):
    '''Sets up file-like objects for logging. Used in
    cases where it is hard just return the output. Any
    output sent to these file objects is also printed to
    the console

    NOTE: I detest this. It would be much better to use
    logging like it's intended
    '''
    self.out = out
    self.err = err

  def parse(self, test_keys):
    '''Takes the dict of key/value pairs describing a FrameworkTest
    and collects all variables needed by this FrameworkTestType

    Raises AttributeError if required keys are missing
    '''
    if all (arg in test_keys for arg in self.args):
      self.__dict__.update({ arg:test_keys[arg] for arg in self.args})
      return self
    else: # This is quite common - most tests don't support all types
      raise AttributeError("A %s requires the benchmark_config.json to contain %s"%(self.name,self.args))

  def request_headers_and_body(self, url):
    '''
    Downloads a URL and returns the HTTP response headers
    and body content as a tuple
    '''
    print "Accessing URL %s:" % url
    self.err.write("Accessing URL %s \n" % url)
    self.out.write("Accessing URL %s \n" % url)

    headers = { 'Accept': self.accept_header}
    r = requests.get(url, timeout=15, headers=headers)

    try:
      r.raise_for_status() # Throws on non-200
      headers = r.headers
      body = r.content
      self.out.write(str(headers))
      self.out.write(body)
      b = 40
      print "  Response (trimmed to %d bytes): \"%s\"" % (b, body.strip()[:b])
      return headers, body
    except requests.HTTPError as err:
      self.err.write(err + '\n')
      return None, None

  def verify(self, base_url):
    '''Accesses URL used by this test type and checks the return
    values for correctness. Most test types run multiple checks,
    so this returns a list of results. Each result is a 3-tuple
    of (String result, String reason, String urlTested).

    - result : 'pass','warn','fail'
    - reason : Short human-readable reason if result was
        warn or fail. Please do not print the response as part of this,
        other parts of TFB will do that based upon the current logging
        settings if this method indicates a failure happened
    - urlTested: The exact URL that was queried

    Subclasses should make a best-effort attempt to report as many
    failures and warnings as they can to help users avoid needing
    to run TFB repeatedly while debugging
    '''
    # TODO make String result into an enum to enforce
    raise NotImplementedError("Subclasses must provide verify")

  def get_url(self):
    '''Returns the URL for this test, like '/json'''
    # This is a method because each test type uses a different key
    # for their URL so the base class can't know which arg is the URL
    raise NotImplementedError("Subclasses must provide verify")

  def copy(self):
    '''Returns a copy that can be safely modified. Use before calling
    parse'''
    return copy.copy(self)

<|endoftext|>


<commit_before># Copyright 2017 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

class _Info(object):

  def __init__(self, name, _type=None, entry_type=None):
    self._name = name
    self._type = _type
    if entry_type is not None and self._type != 'GenericSet':
      raise ValueError(
          'entry_type should only be specified if _type is GenericSet')
    self._entry_type = entry_type

  @property
  def name(self):
    return self._name

  @property
  def type(self):
    return self._type

  @property
  def entry_type(self):
    return self._entry_type

ANGLE_REVISIONS = _Info('angleRevisions', 'GenericSet', str)
ARCHITECTURES = _Info('architectures', 'GenericSet', str)
BENCHMARKS = _Info('benchmarks', 'GenericSet', str)
BENCHMARK_START = _Info('benchmarkStart', 'DateRange')
BENCHMARK_DESCRIPTIONS = _Info('benchmarkDescriptions', 'GenericSet', str)
BOTS = _Info('bots', 'GenericSet', str)
BUG_COMPONENTS = _Info('bugComponents', 'GenericSet', str)
BUILDS = _Info('builds', 'GenericSet', int)
CATAPULT_REVISIONS = _Info('catapultRevisions', 'GenericSet', str)
CHROMIUM_COMMIT_POSITIONS = _Info('chromiumCommitPositions', 'GenericSet', int)
CHROMIUM_REVISIONS = _Info('chromiumRevisions', 'GenericSet', str)
DEVICE_IDS = _Info('deviceIds', 'GenericSet', str)
FUCHSIA_GARNET_REVISIONS = _Info('fuchsiaGarnetRevisions', 'GenericSet', str)
FUCHSIA_PERIDOT_REVISIONS = _Info('fuchsiaPeridotRevisions', 'GenericSet', str)
FUCHSIA_TOPAZ_REVISIONS = _Info('fuchsiaTopazRevisions', 'GenericSet', str)
FUCHSIA_ZIRCON_REVISIONS = _Info('fuchsiaZirconRevisions', 'GenericSet', str)
GPUS = _Info('gpus', 'GenericSet', str)
GROUPING_PATH = _Info('groupingPath')
HAD_FAILURES = _Info('hadFailures', 'GenericSet', bool)
IS_REFERENCE_BUILD = _Info('isReferenceBuild', 'GenericSet', bool)
LABELS = _Info('labels', 'GenericSet', str)
LOG_URLS = _Info('logUrls', 'GenericSet', str)
MASTERS = _Info('masters', 'GenericSet', str)
MEMORY_AMOUNTS = _Info('memoryAmounts', 'GenericSet', int)
MERGED_FROM = _Info('mergedFrom', 'RelatedHistogramMap')
MERGED_TO = _Info('mergedTo', 'RelatedHistogramMap')
OS_NAMES = _Info('osNames', 'GenericSet', str)
OS_VERSIONS = _Info('osVersions', 'GenericSet', str)
OWNERS = _Info('owners', 'GenericSet', str)
PRODUCT_VERSIONS = _Info('productVersions', 'GenericSet', str)
RELATED_NAMES = _Info('relatedNames', 'GenericSet', str)
SKIA_REVISIONS = _Info('skiaRevisions', 'GenericSet', str)
STORIES = _Info('stories', 'GenericSet', str)
STORYSET_REPEATS = _Info('storysetRepeats', 'GenericSet', int)
STORY_TAGS = _Info('storyTags', 'GenericSet', str)
SUMMARY_KEYS = _Info('summaryKeys', 'GenericSet', str)
TAG_MAP = _Info('tagmap', 'TagMap')
TEST_PATH = _Info('testPath', 'GenericSet', str)
TRACE_START = _Info('traceStart', 'DateRange')
TRACE_URLS = _Info('traceUrls', 'GenericSet', str)
V8_COMMIT_POSITIONS = _Info('v8CommitPositions', 'DateRange')
V8_REVISIONS = _Info('v8Revisions', 'GenericSet', str)
WEBRTC_REVISIONS = _Info('webrtcRevisions', 'GenericSet', str)

def GetTypeForName(name):
  for info in globals().itervalues():
    if isinstance(info, _Info) and info.name == name:
      return info.type

def AllInfos():
  for info in globals().itervalues():
    if isinstance(info, _Info):
      yield info

def AllNames():
  for info in AllInfos():
    yield info.name
<commit_msg>Histogram - Cache info types<commit_after># Copyright 2017 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

class _Info(object):

  def __init__(self, name, _type=None, entry_type=None):
    self._name = name
    self._type = _type
    if entry_type is not None and self._type != 'GenericSet':
      raise ValueError(
          'entry_type should only be specified if _type is GenericSet')
    self._entry_type = entry_type

  @property
  def name(self):
    return self._name

  @property
  def type(self):
    return self._type

  @property
  def entry_type(self):
    return self._entry_type

ANGLE_REVISIONS = _Info('angleRevisions', 'GenericSet', str)
ARCHITECTURES = _Info('architectures', 'GenericSet', str)
BENCHMARKS = _Info('benchmarks', 'GenericSet', str)
BENCHMARK_START = _Info('benchmarkStart', 'DateRange')
BENCHMARK_DESCRIPTIONS = _Info('benchmarkDescriptions', 'GenericSet', str)
BOTS = _Info('bots', 'GenericSet', str)
BUG_COMPONENTS = _Info('bugComponents', 'GenericSet', str)
BUILDS = _Info('builds', 'GenericSet', int)
CATAPULT_REVISIONS = _Info('catapultRevisions', 'GenericSet', str)
CHROMIUM_COMMIT_POSITIONS = _Info('chromiumCommitPositions', 'GenericSet', int)
CHROMIUM_REVISIONS = _Info('chromiumRevisions', 'GenericSet', str)
DEVICE_IDS = _Info('deviceIds', 'GenericSet', str)
FUCHSIA_GARNET_REVISIONS = _Info('fuchsiaGarnetRevisions', 'GenericSet', str)
FUCHSIA_PERIDOT_REVISIONS = _Info('fuchsiaPeridotRevisions', 'GenericSet', str)
FUCHSIA_TOPAZ_REVISIONS = _Info('fuchsiaTopazRevisions', 'GenericSet', str)
FUCHSIA_ZIRCON_REVISIONS = _Info('fuchsiaZirconRevisions', 'GenericSet', str)
GPUS = _Info('gpus', 'GenericSet', str)
GROUPING_PATH = _Info('groupingPath')
HAD_FAILURES = _Info('hadFailures', 'GenericSet', bool)
IS_REFERENCE_BUILD = _Info('isReferenceBuild', 'GenericSet', bool)
LABELS = _Info('labels', 'GenericSet', str)
LOG_URLS = _Info('logUrls', 'GenericSet', str)
MASTERS = _Info('masters', 'GenericSet', str)
MEMORY_AMOUNTS = _Info('memoryAmounts', 'GenericSet', int)
MERGED_FROM = _Info('mergedFrom', 'RelatedHistogramMap')
MERGED_TO = _Info('mergedTo', 'RelatedHistogramMap')
OS_NAMES = _Info('osNames', 'GenericSet', str)
OS_VERSIONS = _Info('osVersions', 'GenericSet', str)
OWNERS = _Info('owners', 'GenericSet', str)
PRODUCT_VERSIONS = _Info('productVersions', 'GenericSet', str)
RELATED_NAMES = _Info('relatedNames', 'GenericSet', str)
SKIA_REVISIONS = _Info('skiaRevisions', 'GenericSet', str)
STORIES = _Info('stories', 'GenericSet', str)
STORYSET_REPEATS = _Info('storysetRepeats', 'GenericSet', int)
STORY_TAGS = _Info('storyTags', 'GenericSet', str)
SUMMARY_KEYS = _Info('summaryKeys', 'GenericSet', str)
TAG_MAP = _Info('tagmap', 'TagMap')
TEST_PATH = _Info('testPath', 'GenericSet', str)
TRACE_START = _Info('traceStart', 'DateRange')
TRACE_URLS = _Info('traceUrls', 'GenericSet', str)
V8_COMMIT_POSITIONS = _Info('v8CommitPositions', 'DateRange')
V8_REVISIONS = _Info('v8Revisions', 'GenericSet', str)
WEBRTC_REVISIONS = _Info('webrtcRevisions', 'GenericSet', str)

def _CreateCachedInfoTypes():
  info_types = {}
  for info in globals().itervalues():
    if isinstance(info, _Info):
      info_types[info.name] = info
  return info_types

_CACHED_INFO_TYPES = _CreateCachedInfoTypes()

def GetTypeForName(name):
  info = _CACHED_INFO_TYPES.get(name)
  if info:
    return info.type

def AllInfos():
  for info in _CACHED_INFO_TYPES.itervalues():
    yield info

def AllNames():
  for info in AllInfos():
    yield info.name
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
from mock import Mock, PropertyMock, patch
from flask import current_app, url_for, session
from flask_oauthlib.client import OAuthException
from app import db
from base import UnitTestCase
from app.models import User
from app.auth.views import facebook
from app.main import helpers
from datetime import datetime, timedelta
from uuid import uuid4

class AuthViewTestCase(UnitTestCase):

  def setUp(self):
    super(AuthViewTestCase, self).setUp()
    self.client = self.app.test_client(use_cookies=True)

class BeforeRequestTestCase(AuthViewTestCase):
  '''Testing: @auth.route('/before_request')'''

  def test_update_last_seen(self):
    '''verify last_seen is updated properly every 15min
    1. Create a user
    2. Log in user and modify last_seen value
    3. Request index view
    4. Assert that last_seen user attribute has been updated
    '''
    u = User(fb_id='23', email='john@example.com', name='John Doe',
            username='john', avatar_url=uuid4().hex + '.jpg')
    db.session.add(u)
    db.session.commit()
    before_last_seen = u.last_seen
    with self.client as c:
      with c.session_transaction() as sess:
        sess['user_id'] = u.id
        sess['last_seen'] = datetime.utcnow() - timedelta(minutes=30)
        sess['_fresh'] = True
      response = c.get(url_for('main.index'))
      self.assertTrue(u.last_seen > before_last_seen)

class FBLoginTestCase(AuthViewTestCase):
  '''Testing: @auth.route('/fb-login/authorized')'''

  @staticmethod
  def mock_facebook_auth():
    '''mock Facebook authentication'''
    mock_fb_resp = Mock()
    mock_fb_resp.return_value = {
      'access_token': 'dummy_token',
      'expires': '5183883'
    }
    return mock_fb_resp

  @staticmethod
  def mock_facebook_info():
    '''mock Facebook user information call'''
    mock_fb_info = Mock()
    type(mock_fb_info.return_value).data = PropertyMock(
                              return_value= { 'id': '12908098',
                                              'email': 'john@testing.com',
                                              'name': 'John Doe',
                                              'gender': 'male',
                                              'data': {
                                                'url': 'http://test-image.png' }
                                            })
    return mock_fb_info

  @staticmethod
  def mock_facebook_error_info():
    '''mock Facebook user information call returning an error'''
    mock_fb_info = Mock()
    type(mock_fb_info.return_value).data = PropertyMock(
                              return_value= { 'error': 'User not found'})
    return mock_fb_info

  def test_login_user_fb_auth(self):
    '''verify a new user is created when login with FB for the first time
    1. Create mock objects
    2. Verfiy user does not exist in the DB
    3. Call the login method
    4. Verify the user has been created and it is redirected to index'''

    mock_fb_resp = FBLoginTestCase.mock_facebook_auth()
    mock_fb_info = FBLoginTestCase.mock_facebook_info()

    mock_save_avatar = Mock(name='save_avatar')
    mock_save_avatar.return_value = 'testimage.jpg'

    self.assertTrue(User.get_user('john@testing.com') is None)

    with patch.object(facebook, 'authorized_response', mock_fb_resp):
      with patch.object(facebook, 'get', mock_fb_info):
        with patch.object(helpers, 'save_avatar', mock_save_avatar):
          resp = self.client.get(url_for('auth.facebook_authorized'),
                                  follow_redirects=True)
          self.assertTrue(isinstance(User.get_user('john@testing.com'), User))
          self.assertTrue('john' in resp.get_data(as_text=True))

  def test_already_login_user_fb_auth(self):
    '''if user is already authenticated verify it is redirected
    to index
    1. Create a user
    2. Log in user by adding it to session
    3. Request fb-login view
    4. Assert user is redirected to index
    '''
    u = User(fb_id='23', email='john@example.com', name='John Doe',
            username='john', avatar_url=uuid4().hex + '.jpg')
    db.session.add(u)
    db.session.commit()
    with self.client as c:
      with c.session_transaction() as sess:
        sess['user_id'] = u.id
        sess['_fresh'] = True
      response = c.get(url_for('auth.fb_login'),follow_redirects=True)
      self.assertTrue('Welcome to TradyFit' in response.get_data(as_text=True))

  def test_user_denied_login(self):
    '''user denied login with FB'''
    mock_fb_resp = Mock(return_value=None)
    with patch.object(facebook, 'authorized_response', mock_fb_resp):
      resp = self.client.get(url_for('auth.facebook_authorized'),
                              follow_redirects=True)
      content = resp.get_data(as_text=True)
      self.assertTrue('Log In with Facebook' in content)
      self.assertTrue('You denied the request to sign in.' in content)

  def test_oauth_login_exception(self):
    '''An exception has been raised from FB login API call'''
    mock_fb_resp = Mock(return_value=OAuthException('error'))
    with patch.object(facebook, 'authorized_response', mock_fb_resp):
      resp = self.client.get(url_for('auth.facebook_authorized'),
                              follow_redirects=True)
      content = resp.get_data(as_text=True)
      self.assertTrue('Log In with Facebook' in content)
      self.assertTrue('Something went wrong, please try to sign in later.' in
                      content)

  def test_user_info_error(self):
    '''FB returns an error when asking for user's information'''
    mock_fb_resp = FBLoginTestCase.mock_facebook_auth()
    mock_fb_info = FBLoginTestCase.mock_facebook_error_info()

    with patch.object(facebook, 'authorized_response', mock_fb_resp):
      with patch.object(facebook, 'get', mock_fb_info):
        resp = self.client.get(url_for('auth.facebook_authorized'),
                              follow_redirects=True)
        content = resp.get_data(as_text=True)
        self.assertTrue('Log In with Facebook' in content)
        self.assertTrue('Something went wrong, please try to sign in later.' in
                      content)

class LogoutTestCase(AuthViewTestCase):
  '''Testing: @auth.route('/logout')'''

  def test_fb_cookies_removed(self):
    u = User(fb_id='23', email='john@example.com', name='John Doe',
            username='john', avatar_url='avatar.jpg')
    db.session.add(u)
    db.session.commit()
    with self.client as c:
      with c.session_transaction() as sess:
        sess['user_id'] = u.id
        sess['fb_oauth'] = ('fake_token', '')
        sess['_fresh'] = True
      response = c.get(url_for('auth.logout'),follow_redirects=True)
      self.assertTrue('fb_oauth' not in session)
      self.assertTrue('Log In with Facebook' in response.get_data(as_text=True))
<commit_msg>inherit from ClientTestCase<commit_after># -*- coding: utf-8 -*-
from mock import Mock, PropertyMock, patch
from flask import current_app, url_for, session
from flask_oauthlib.client import OAuthException
from app import db
from base import ClientTestCase
from app.models import User
from app.auth.views import facebook
from app.main import helpers
from datetime import datetime, timedelta
from uuid import uuid4

class BeforeRequestTestCase(ClientTestCase):
  '''Testing: @auth.route('/before_request')'''

  def test_update_last_seen(self):
    '''verify last_seen is updated properly every 15min
    1. Create a user
    2. Log in user and modify last_seen value
    3. Request index view
    4. Assert that last_seen user attribute has been updated
    '''
    u = User(fb_id='23', email='john@example.com', name='John Doe',
            username='john', avatar_url=uuid4().hex + '.jpg')
    db.session.add(u)
    db.session.commit()
    before_last_seen = u.last_seen
    with self.client as c:
      with c.session_transaction() as sess:
        sess['user_id'] = u.id
        sess['last_seen'] = datetime.utcnow() - timedelta(minutes=30)
        sess['_fresh'] = True
      response = c.get(url_for('main.index'))
      self.assertTrue(u.last_seen > before_last_seen)

class FBLoginTestCase(ClientTestCase):
  '''Testing: @auth.route('/fb-login/authorized')'''

  @staticmethod
  def mock_facebook_auth():
    '''mock Facebook authentication'''
    mock_fb_resp = Mock()
    mock_fb_resp.return_value = {
      'access_token': 'dummy_token',
      'expires': '5183883'
    }
    return mock_fb_resp

  @staticmethod
  def mock_facebook_info():
    '''mock Facebook user information call'''
    mock_fb_info = Mock()
    type(mock_fb_info.return_value).data = PropertyMock(
                              return_value= { 'id': '12908098',
                                              'email': 'john@testing.com',
                                              'name': 'John Doe',
                                              'gender': 'male',
                                              'data': {
                                                'url': 'http://test-image.png' }
                                            })
    return mock_fb_info

  @staticmethod
  def mock_facebook_error_info():
    '''mock Facebook user information call returning an error'''
    mock_fb_info = Mock()
    type(mock_fb_info.return_value).data = PropertyMock(
                              return_value= { 'error': 'User not found'})
    return mock_fb_info

  def test_login_user_fb_auth(self):
    '''verify a new user is created when login with FB for the first time
    1. Create mock objects
    2. Verfiy user does not exist in the DB
    3. Call the login method
    4. Verify the user has been created and it is redirected to index'''

    mock_fb_resp = FBLoginTestCase.mock_facebook_auth()
    mock_fb_info = FBLoginTestCase.mock_facebook_info()

    mock_save_avatar = Mock(name='save_avatar')
    mock_save_avatar.return_value = 'testimage.jpg'

    self.assertTrue(User.get_user('john@testing.com') is None)

    with patch.object(facebook, 'authorized_response', mock_fb_resp):
      with patch.object(facebook, 'get', mock_fb_info):
        with patch.object(helpers, 'save_avatar', mock_save_avatar):
          resp = self.client.get(url_for('auth.facebook_authorized'),
                                  follow_redirects=True)
          self.assertTrue(isinstance(User.get_user('john@testing.com'), User))
          self.assertTrue('john' in resp.get_data(as_text=True))

  def test_already_login_user_fb_auth(self):
    '''if user is already authenticated verify it is redirected
    to index
    1. Create a user
    2. Log in user by adding it to session
    3. Request fb-login view
    4. Assert user is redirected to index
    '''
    u = User(fb_id='23', email='john@example.com', name='John Doe',
            username='john', avatar_url=uuid4().hex + '.jpg')
    db.session.add(u)
    db.session.commit()
    with self.client as c:
      with c.session_transaction() as sess:
        sess['user_id'] = u.id
        sess['_fresh'] = True
      response = c.get(url_for('auth.fb_login'),follow_redirects=True)
      self.assertTrue('Welcome to TradyFit' in response.get_data(as_text=True))

  def test_user_denied_login(self):
    '''user denied login with FB'''
    mock_fb_resp = Mock(return_value=None)
    with patch.object(facebook, 'authorized_response', mock_fb_resp):
      resp = self.client.get(url_for('auth.facebook_authorized'),
                              follow_redirects=True)
      content = resp.get_data(as_text=True)
      self.assertTrue('Log In with Facebook' in content)
      self.assertTrue('You denied the request to sign in.' in content)

  def test_oauth_login_exception(self):
    '''An exception has been raised from FB login API call'''
    mock_fb_resp = Mock(return_value=OAuthException('error'))
    with patch.object(facebook, 'authorized_response', mock_fb_resp):
      resp = self.client.get(url_for('auth.facebook_authorized'),
                              follow_redirects=True)
      content = resp.get_data(as_text=True)
      self.assertTrue('Log In with Facebook' in content)
      self.assertTrue('Something went wrong, please try to sign in later.' in
                      content)

  def test_user_info_error(self):
    '''FB returns an error when asking for user's information'''
    mock_fb_resp = FBLoginTestCase.mock_facebook_auth()
    mock_fb_info = FBLoginTestCase.mock_facebook_error_info()

    with patch.object(facebook, 'authorized_response', mock_fb_resp):
      with patch.object(facebook, 'get', mock_fb_info):
        resp = self.client.get(url_for('auth.facebook_authorized'),
                              follow_redirects=True)
        content = resp.get_data(as_text=True)
        self.assertTrue('Log In with Facebook' in content)
        self.assertTrue('Something went wrong, please try to sign in later.' in
                      content)

class LogoutTestCase(ClientTestCase):
  '''Testing: @auth.route('/logout')'''

  def test_fb_cookies_removed(self):
    u = User(fb_id='23', email='john@example.com', name='John Doe',
            username='john', avatar_url='avatar.jpg')
    db.session.add(u)
    db.session.commit()
    with self.client as c:
      with c.session_transaction() as sess:
        sess['user_id'] = u.id
        sess['fb_oauth'] = ('fake_token', '')
        sess['_fresh'] = True
      response = c.get(url_for('auth.logout'),follow_redirects=True)
      self.assertTrue('fb_oauth' not in session)
      self.assertTrue('Log In with Facebook' in response.get_data(as_text=True))
<|endoftext|>


<commit_before># Copyright 2013-2020 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)

from spack import *

import sys

class Caliper(CMakePackage):
    """Caliper is a program instrumentation and performance measurement
    framework. It is designed as a performance analysis toolbox in a
    library, allowing one to bake performance analysis capabilities
    directly into applications and activate them at runtime.
    """

    homepage = "https://github.com/LLNL/Caliper"
    git      = "https://github.com/LLNL/Caliper.git"

    version('master')
    version('2.4.0', tag='v2.4.0')
    version('2.3.0', tag='v2.3.0')
    version('2.2.0', tag='v2.2.0')
    version('2.1.1', tag='v2.1.1')
    version('2.0.1', tag='v2.0.1')
    version('1.9.1', tag='v1.9.1')
    version('1.9.0', tag='v1.9.0')
    version('1.8.0', tag='v1.8.0')
    version('1.7.0', tag='v1.7.0')

    is_linux = sys.platform.startswith('linux')
    variant('shared', default=True,
            description='Build shared libraries')
    variant('adiak', default=True,
            description='Enable Adiak support')
    variant('mpi', default=True,
            description='Enable MPI wrappers')
    variant('dyninst', default=False,
            description='Enable symbol translation support with dyninst')
    # libunwind has some issues on Mac
    variant('callpath', default=sys.platform != 'darwin',
            description='Enable callpath service (requires libunwind)')
    # pthread_self() signature is incompatible with PAPI_thread_init() on Mac
    variant('papi', default=sys.platform != 'darwin',
            description='Enable PAPI service')
    variant('libpfm', default=is_linux,
            description='Enable libpfm (perf_events) service')
    # Gotcha is Linux-only
    variant('gotcha', default=is_linux,
            description='Enable GOTCHA support')
    variant('sampler', default=is_linux,
            description='Enable sampling support on Linux')
    variant('sosflow', default=False,
            description='Enable SOSflow support')

    depends_on('adiak@0.1:0.99', when='@2.2: +adiak')

    depends_on('dyninst@9.3.0:9.99', when='@:1.99 +dyninst')
    depends_on('dyninst@10.0:10.99', when='@2: +dyninst')

    depends_on('papi@5.3:5.99', when='@:2.2 +papi')
    depends_on('papi@5.3:6.99', when='@2.3: +papi')

    depends_on('libpfm4@4.8:4.99', when='+libpfm')

    depends_on('mpi', when='+mpi')
    depends_on('unwind@1.2:1.99', when='+callpath')

    depends_on('sosflow@spack', when='@1.0:1.99+sosflow')

    depends_on('cmake',  type='build')
    depends_on('python', type='build')

    # sosflow support not yet in 2.0
    conflicts('+sosflow', '@2.0.0:2.4.99')
    conflicts('+adiak', '@:2.1.99')

    def cmake_args(self):
        spec = self.spec

        args = [
            ('-DPYTHON_EXECUTABLE=%s' %
                spec['python'].command.path),
            '-DBUILD_TESTING=Off',
            '-DBUILD_DOCS=Off',
            '-DBUILD_SHARED_LIBS=%s' % ('On' if '+shared'  in spec else 'Off'),
            '-DWITH_ADIAK=%s'    % ('On' if '+adiak'    in spec else 'Off'),
            '-DWITH_DYNINST=%s'  % ('On' if '+dyninst'  in spec else 'Off'),
            '-DWITH_CALLPATH=%s' % ('On' if '+callpath' in spec else 'Off'),
            '-DWITH_GOTCHA=%s'   % ('On' if '+gotcha'   in spec else 'Off'),
            '-DWITH_PAPI=%s'     % ('On' if '+papi'     in spec else 'Off'),
            '-DWITH_LIBPFM=%s'   % ('On' if '+libpfm'   in spec else 'Off'),
            '-DWITH_SOSFLOW=%s'  % ('On' if '+sosflow'  in spec else 'Off'),
            '-DWITH_SAMPLER=%s'  % ('On' if '+sampler'  in spec else 'Off'),
            '-DWITH_MPI=%s'      % ('On' if '+mpi'      in spec else 'Off')
        ]

        if '+papi' in spec:
            args.append('-DPAPI_PREFIX=%s'    % spec['papi'].prefix)
        if '+libpfm' in spec:
            args.append('-DLIBPFM_INSTALL=%s' % spec['libpfm4'].prefix)
        if '+sosflow' in spec:
            args.append('-DSOS_PREFIX=%s'     % spec['sosflow'].prefix)
        if '+callpath' in spec:
            args.append('-DLIBUNWIND_PREFIX=%s' % spec['libunwind'].prefix)

        if '+mpi' in spec:
            args.append('-DMPI_C_COMPILER=%s' % spec['mpi'].mpicc)
            args.append('-DMPI_CXX_COMPILER=%s' % spec['mpi'].mpicxx)

        return args
<commit_msg>caliper: Remove support for deprecated Dyninst versions (#18275)<commit_after># Copyright 2013-2020 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)

from spack import *

import sys

class Caliper(CMakePackage):
    """Caliper is a program instrumentation and performance measurement
    framework. It is designed as a performance analysis toolbox in a
    library, allowing one to bake performance analysis capabilities
    directly into applications and activate them at runtime.
    """

    homepage = "https://github.com/LLNL/Caliper"
    git      = "https://github.com/LLNL/Caliper.git"

    version('master')
    version('2.4.0', tag='v2.4.0')
    version('2.3.0', tag='v2.3.0')
    version('2.2.0', tag='v2.2.0')
    version('2.1.1', tag='v2.1.1')
    version('2.0.1', tag='v2.0.1')
    version('1.9.1', tag='v1.9.1')
    version('1.9.0', tag='v1.9.0')
    version('1.8.0', tag='v1.8.0')
    version('1.7.0', tag='v1.7.0')

    is_linux = sys.platform.startswith('linux')
    variant('shared', default=True,
            description='Build shared libraries')
    variant('adiak', default=True,
            description='Enable Adiak support')
    variant('mpi', default=True,
            description='Enable MPI wrappers')
    variant('dyninst', default=False,
            description='Enable symbol translation support with dyninst')
    # libunwind has some issues on Mac
    variant('callpath', default=sys.platform != 'darwin',
            description='Enable callpath service (requires libunwind)')
    # pthread_self() signature is incompatible with PAPI_thread_init() on Mac
    variant('papi', default=sys.platform != 'darwin',
            description='Enable PAPI service')
    variant('libpfm', default=is_linux,
            description='Enable libpfm (perf_events) service')
    # Gotcha is Linux-only
    variant('gotcha', default=is_linux,
            description='Enable GOTCHA support')
    variant('sampler', default=is_linux,
            description='Enable sampling support on Linux')
    variant('sosflow', default=False,
            description='Enable SOSflow support')

    depends_on('adiak@0.1:0.99', when='@2.2: +adiak')

    depends_on('dyninst@10.0:10.99', when='@2: +dyninst')

    depends_on('papi@5.3:5.99', when='@:2.2 +papi')
    depends_on('papi@5.3:6.99', when='@2.3: +papi')

    depends_on('libpfm4@4.8:4.99', when='+libpfm')

    depends_on('mpi', when='+mpi')
    depends_on('unwind@1.2:1.99', when='+callpath')

    depends_on('sosflow@spack', when='@1.0:1.99+sosflow')

    depends_on('cmake',  type='build')
    depends_on('python', type='build')

    # sosflow support not yet in 2.0
    conflicts('+sosflow', '@2.0.0:2.4.99')
    conflicts('+adiak', '@:2.1.99')

    # The Dyninst 9.X used by v1.9.X is deprecated
    conflicts('+dyninst', when='@:1.99',
              msg='Dyninst unsupported by version <=2.0.1')

    def cmake_args(self):
        spec = self.spec

        args = [
            ('-DPYTHON_EXECUTABLE=%s' %
                spec['python'].command.path),
            '-DBUILD_TESTING=Off',
            '-DBUILD_DOCS=Off',
            '-DBUILD_SHARED_LIBS=%s' % ('On' if '+shared'  in spec else 'Off'),
            '-DWITH_ADIAK=%s'    % ('On' if '+adiak'    in spec else 'Off'),
            '-DWITH_DYNINST=%s'  % ('On' if '+dyninst'  in spec else 'Off'),
            '-DWITH_CALLPATH=%s' % ('On' if '+callpath' in spec else 'Off'),
            '-DWITH_GOTCHA=%s'   % ('On' if '+gotcha'   in spec else 'Off'),
            '-DWITH_PAPI=%s'     % ('On' if '+papi'     in spec else 'Off'),
            '-DWITH_LIBPFM=%s'   % ('On' if '+libpfm'   in spec else 'Off'),
            '-DWITH_SOSFLOW=%s'  % ('On' if '+sosflow'  in spec else 'Off'),
            '-DWITH_SAMPLER=%s'  % ('On' if '+sampler'  in spec else 'Off'),
            '-DWITH_MPI=%s'      % ('On' if '+mpi'      in spec else 'Off')
        ]

        if '+papi' in spec:
            args.append('-DPAPI_PREFIX=%s'    % spec['papi'].prefix)
        if '+libpfm' in spec:
            args.append('-DLIBPFM_INSTALL=%s' % spec['libpfm4'].prefix)
        if '+sosflow' in spec:
            args.append('-DSOS_PREFIX=%s'     % spec['sosflow'].prefix)
        if '+callpath' in spec:
            args.append('-DLIBUNWIND_PREFIX=%s' % spec['libunwind'].prefix)

        if '+mpi' in spec:
            args.append('-DMPI_C_COMPILER=%s' % spec['mpi'].mpicc)
            args.append('-DMPI_CXX_COMPILER=%s' % spec['mpi'].mpicxx)

        return args
<|endoftext|>


<commit_before>##############################################################################
# Copyright (c) 2013-2016, Lawrence Livermore National Security, LLC.
# Produced at the Lawrence Livermore National Laboratory.
#
# This file is part of Spack.
# Created by Todd Gamblin, tgamblin@llnl.gov, All rights reserved.
# LLNL-CODE-647188
#
# For details, see https://github.com/llnl/spack
# Please also see the LICENSE file for our notice and the LGPL.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License (as
# published by the Free Software Foundation) version 2.1, February 1999.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and
# conditions of the GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
##############################################################################
import subprocess

from spack import *

class Gromacs(Package):
    """
    GROMACS (GROningen MAchine for Chemical Simulations) is a molecular dynamics package primarily designed for
    simulations of proteins, lipids and nucleic acids. It was originally developed in the Biophysical Chemistry
    department of University of Groningen, and is now maintained by contributors in universities and research centers
    across the world.

    GROMACS is one of the fastest and most popular software packages available and can run on CPUs as well as GPUs.
    It is free, open source released under the GNU General Public License. Starting from version 4.6, GROMACS is
    released under the GNU Lesser General Public License.
    """

    homepage = 'http://www.gromacs.org'
    url = 'ftp://ftp.gromacs.org/pub/gromacs/gromacs-5.1.2.tar.gz'

    version('5.1.2', '614d0be372f1a6f1f36382b7a6fcab98')

    variant('mpi', default=True, description='Activate MPI support')
    variant('shared', default=True, description='Enables the build of shared libraries')
    variant('debug', default=False, description='Enables debug mode')
    variant('double', default=False, description='Produces a double precision version of the executables')
    variant('plumed', default=False, description='Enable PLUMED support')

    depends_on('mpi', when='+mpi')
    depends_on('plumed+mpi', when='+plumed+mpi')
    depends_on('plumed~mpi', when='+plumed~mpi')
    depends_on('fftw')
    depends_on('cmake', type='build')

    # TODO : add GPU support

    def patch(self):
        if '+plumed' in self.spec:
            self.spec['plumed'].package.apply_patch(self)

    def install(self, spec, prefix):

        options = []

        if '+mpi' in spec:
            options.append('-DGMX_MPI:BOOL=ON')

        if '+double' in spec:
            options.append('-DGMX_DOUBLE:BOOL=ON')

        if '~shared' in spec:
            options.append('-DBUILD_SHARED_LIBS:BOOL=OFF')

        if '+debug' in spec:
            options.append('-DCMAKE_BUILD_TYPE:STRING=Debug')
        else:
            options.append('-DCMAKE_BUILD_TYPE:STRING=Release')

        options.extend(std_cmake_args)

        with working_dir('spack-build', create=True):

            cmake('..', *options)
            make()
            make('install')
<commit_msg>qa : flake8 issues<commit_after>##############################################################################
# Copyright (c) 2013-2016, Lawrence Livermore National Security, LLC.
# Produced at the Lawrence Livermore National Laboratory.
#
# This file is part of Spack.
# Created by Todd Gamblin, tgamblin@llnl.gov, All rights reserved.
# LLNL-CODE-647188
#
# For details, see https://github.com/llnl/spack
# Please also see the LICENSE file for our notice and the LGPL.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License (as
# published by the Free Software Foundation) version 2.1, February 1999.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and
# conditions of the GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
##############################################################################

from spack import *

class Gromacs(Package):
    """GROMACS (GROningen MAchine for Chemical Simulations) is a molecular
    dynamics package primarily designed for simulations of proteins, lipids
    and nucleic acids. It was originally developed in the Biophysical
    Chemistry department of University of Groningen, and is now maintained
    by contributors in universities and research centers across the world.

    GROMACS is one of the fastest and most popular software packages
    available and can run on CPUs as well as GPUs. It is free, open source
    released under the GNU General Public License. Starting from version 4.6,
    GROMACS is released under the GNU Lesser General Public License.
    """

    homepage = 'http://www.gromacs.org'
    url = 'ftp://ftp.gromacs.org/pub/gromacs/gromacs-5.1.2.tar.gz'

    version('5.1.2', '614d0be372f1a6f1f36382b7a6fcab98')

    variant('mpi', default=True, description='Activate MPI support')
    variant('shared', default=True,
            description='Enables the build of shared libraries')
    variant('debug', default=False, description='Enables debug mode')
    variant('double', default=False, description='Produces a double precision version of the executables')  # NOQA: ignore=E501
    variant('plumed', default=False, description='Enable PLUMED support')

    depends_on('mpi', when='+mpi')
    depends_on('plumed+mpi', when='+plumed+mpi')
    depends_on('plumed~mpi', when='+plumed~mpi')
    depends_on('fftw')
    depends_on('cmake', type='build')

    # TODO : add GPU support

    def patch(self):
        if '+plumed' in self.spec:
            self.spec['plumed'].package.apply_patch(self)

    def install(self, spec, prefix):

        options = []

        if '+mpi' in spec:
            options.append('-DGMX_MPI:BOOL=ON')

        if '+double' in spec:
            options.append('-DGMX_DOUBLE:BOOL=ON')

        if '~shared' in spec:
            options.append('-DBUILD_SHARED_LIBS:BOOL=OFF')

        if '+debug' in spec:
            options.append('-DCMAKE_BUILD_TYPE:STRING=Debug')
        else:
            options.append('-DCMAKE_BUILD_TYPE:STRING=Release')

        options.extend(std_cmake_args)

        with working_dir('spack-build', create=True):

            cmake('..', *options)
            make()
            make('install')
<|endoftext|>


<commit_before># Copyright 2013-2021 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)

from spack import *

class Gtkplus(MesonPackage):
    """The GTK+ package contains libraries used for creating graphical user
       interfaces for applications."""

    homepage = "https://www.gtk.org/"
    url      = "https://download.gnome.org/sources/gtk+/3.24/gtk+-3.24.26.tar.xz"

    version('3.24.29', sha256='f57ec4ade8f15cab0c23a80dcaee85b876e70a8823d9105f067ce335a8268caa')
    version('3.24.26', sha256='2cc1b2dc5cad15d25b6abd115c55ffd8331e8d4677745dd3ce6db725b4fff1e9')
    version('3.20.10', sha256='e81da1af1c5c1fee87ba439770e17272fa5c06e64572939814da406859e56b70', deprecated=True)
    version('2.24.32', sha256='b6c8a93ddda5eabe3bfee1eb39636c9a03d2a56c7b62828b359bf197943c582e', deprecated=True)
    version('2.24.31', sha256='68c1922732c7efc08df4656a5366dcc3afdc8791513400dac276009b40954658', deprecated=True)
    version('2.24.25', sha256='38af1020cb8ff3d10dda2c8807f11e92af9d2fa4045de61c62eedb7fbc7ea5b3', deprecated=True)

    variant('cups', default='False', description='enable cups support')

    # See meson.build for version requirements
    depends_on('meson@0.48.0:', when='@3.24:', type='build')
    depends_on('ninja', when='@3.24:', type='build')
    # Needed to build man pages:
    # depends_on('docbook-xml', when='@3.24:', type='build')
    # depends_on('docbook-xsl', when='@3.24:', type='build')
    # depends_on('libxslt', when='@3.24:', type='build')
    depends_on('pkgconfig', type='build')
    depends_on('glib@2.57.2:')
    depends_on('pango@1.41.0:+X')
    depends_on('fribidi@0.19.7:')
    depends_on('atk@2.35.1:')
    depends_on('at-spi2-atk@2.15.1:', when='@3:')
    depends_on('cairo@1.14.0:+X+pdf+gobject')
    depends_on('gdk-pixbuf@2.30.0:')
    depends_on('gobject-introspection@1.39.0:')
    depends_on('shared-mime-info')
    depends_on('libxkbcommon')
    depends_on('librsvg')
    depends_on('xrandr')
    depends_on('libepoxy+glx', when='@3:')
    depends_on('libxi', when='@3:')
    depends_on('inputproto', when='@3:')
    depends_on('fixesproto', when='@3:')
    depends_on('gettext', when='@3:')
    depends_on('cups', when='+cups')

    patch('no-demos.patch', when='@2.0:2')

    def url_for_version(self, version):
        url = 'https://download.gnome.org/sources/gtk+/{0}/gtk+-{1}.tar.xz'
        return url.format(version.up_to(2), version)

    def patch(self):
        # remove disable deprecated flag.
        filter_file(r'CFLAGS="-DGDK_PIXBUF_DISABLE_DEPRECATED $CFLAGS"',
                    '', 'configure', string=True)

        # https://gitlab.gnome.org/GNOME/gtk/-/issues/3776
        if self.spec.satisfies('%gcc@11:'):
            filter_file("    '-Werror=array-bounds',",
                        '', 'meson.build', string=True)

    def setup_run_environment(self, env):
        env.prepend_path("GI_TYPELIB_PATH",
                         join_path(self.prefix.lib, 'girepository-1.0'))

    def setup_dependent_build_environment(self, env, dependent_spec):
        env.prepend_path("XDG_DATA_DIRS", self.prefix.share)
        env.prepend_path("GI_TYPELIB_PATH",
                         join_path(self.prefix.lib, 'girepository-1.0'))

    def setup_dependent_run_environment(self, env, dependent_spec):
        env.prepend_path("XDG_DATA_DIRS", self.prefix.share)
        env.prepend_path("GI_TYPELIB_PATH",
                         join_path(self.prefix.lib, 'girepository-1.0'))

    def meson_args(self):
        args = std_meson_args

        if self.spec.satisfies('platform=darwin'):
            args.extend([
                '-Dx11_backend=false',
                '-Dquartz_backend=true',
            ])

        args.extend([
            '-Dgtk_doc=false',
            '-Dman=false',
            '-Dintrospection=true',
            '-Dwayland_backend=false',
        ])

        return args

    def configure_args(self):
        true = which('true')
        args = [
            '--prefix={0}'.format(self.prefix),
            # disable building of gtk-doc files following #9771
            '--disable-gtk-doc-html',
            'GTKDOC_CHECK={0}'.format(true),
            'GTKDOC_CHECK_PATH={0}'.format(true),
            'GTKDOC_MKPDF={0}'.format(true),
            'GTKDOC_REBASE={0}'.format(true),
        ]
        if '~cups' in self.spec:
            args.append('--disable-cups')
        return args

    @when('@:3.20.10')
    def meson(self, spec, prefix):
        configure(*self.configure_args)

    @when('@:3.20.10')
    def build(self, spec, prefix):
        make()

    @when('@:3.20.10')
    def install(self, spec, prefix):
        make('install')
<commit_msg>gtkplus: fix build of GTK2 versions with gcc-11, skip X tests (#26970)<commit_after># Copyright 2013-2021 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)

from spack import *

class Gtkplus(MesonPackage):
    """The GTK+ package contains libraries used for creating graphical user
       interfaces for applications."""

    homepage = "https://www.gtk.org/"
    url      = "https://download.gnome.org/sources/gtk+/3.24/gtk+-3.24.26.tar.xz"

    version('3.24.29', sha256='f57ec4ade8f15cab0c23a80dcaee85b876e70a8823d9105f067ce335a8268caa')
    version('3.24.26', sha256='2cc1b2dc5cad15d25b6abd115c55ffd8331e8d4677745dd3ce6db725b4fff1e9')
    version('3.20.10', sha256='e81da1af1c5c1fee87ba439770e17272fa5c06e64572939814da406859e56b70', deprecated=True)
    version('2.24.32', sha256='b6c8a93ddda5eabe3bfee1eb39636c9a03d2a56c7b62828b359bf197943c582e', deprecated=True)
    version('2.24.31', sha256='68c1922732c7efc08df4656a5366dcc3afdc8791513400dac276009b40954658', deprecated=True)
    version('2.24.25', sha256='38af1020cb8ff3d10dda2c8807f11e92af9d2fa4045de61c62eedb7fbc7ea5b3', deprecated=True)

    variant('cups', default='False', description='enable cups support')

    # See meson.build for version requirements
    depends_on('meson@0.48.0:', when='@3.24:', type='build')
    depends_on('ninja', when='@3.24:', type='build')
    # Needed to build man pages:
    # depends_on('docbook-xml', when='@3.24:', type='build')
    # depends_on('docbook-xsl', when='@3.24:', type='build')
    # depends_on('libxslt', when='@3.24:', type='build')
    depends_on('pkgconfig', type='build')
    depends_on('glib@2.57.2:')
    depends_on('pango@1.41.0:+X')
    depends_on('fribidi@0.19.7:')
    depends_on('atk@2.35.1:')
    depends_on('at-spi2-atk@2.15.1:', when='@3:')
    depends_on('cairo@1.14.0:+X+pdf+gobject')
    depends_on('gdk-pixbuf@2.30.0:')
    depends_on('gobject-introspection@1.39.0:')
    depends_on('shared-mime-info')
    depends_on('libxkbcommon')
    depends_on('librsvg')
    depends_on('xrandr')
    depends_on('libepoxy+glx', when='@3:')
    depends_on('libxi', when='@3:')
    depends_on('inputproto', when='@3:')
    depends_on('fixesproto', when='@3:')
    depends_on('gettext', when='@3:')
    depends_on('cups', when='+cups')

    patch('no-demos.patch', when='@2.0:2')

    def url_for_version(self, version):
        url = 'https://download.gnome.org/sources/gtk+/{0}/gtk+-{1}.tar.xz'
        return url.format(version.up_to(2), version)

    def patch(self):
        # remove disable deprecated flag.
        filter_file(r'CFLAGS="-DGDK_PIXBUF_DISABLE_DEPRECATED $CFLAGS"',
                    '', 'configure', string=True)

        # https://gitlab.gnome.org/GNOME/gtk/-/issues/3776
        if self.spec.satisfies('@3:%gcc@11:'):
            filter_file("    '-Werror=array-bounds',",
                        '', 'meson.build', string=True)

    def setup_run_environment(self, env):
        env.prepend_path("GI_TYPELIB_PATH",
                         join_path(self.prefix.lib, 'girepository-1.0'))

    def setup_dependent_build_environment(self, env, dependent_spec):
        env.prepend_path("XDG_DATA_DIRS", self.prefix.share)
        env.prepend_path("GI_TYPELIB_PATH",
                         join_path(self.prefix.lib, 'girepository-1.0'))

    def setup_dependent_run_environment(self, env, dependent_spec):
        env.prepend_path("XDG_DATA_DIRS", self.prefix.share)
        env.prepend_path("GI_TYPELIB_PATH",
                         join_path(self.prefix.lib, 'girepository-1.0'))

    def meson_args(self):
        args = std_meson_args

        if self.spec.satisfies('platform=darwin'):
            args.extend([
                '-Dx11_backend=false',
                '-Dquartz_backend=true',
            ])

        args.extend([
            '-Dgtk_doc=false',
            '-Dman=false',
            '-Dintrospection=true',
            '-Dwayland_backend=false',
        ])

        return args

    def configure_args(self):
        true = which('true')
        args = [
            '--prefix={0}'.format(self.prefix),
            # disable building of gtk-doc files following #9771
            '--disable-gtk-doc-html',
            'GTKDOC_CHECK={0}'.format(true),
            'GTKDOC_CHECK_PATH={0}'.format(true),
            'GTKDOC_MKPDF={0}'.format(true),
            'GTKDOC_REBASE={0}'.format(true),
        ]
        if '~cups' in self.spec:
            args.append('--disable-cups')
        return args

    @when('@:3.20.10')
    def meson(self, spec, prefix):
        configure(*self.configure_args)

    @when('@:3.20.10')
    def build(self, spec, prefix):
        make()

    @when('@:3.20.10')
    def install(self, spec, prefix):
        make('install')

    def check(self):
        """All build time checks open windows in the X server, don't do that"""
        pass
<|endoftext|>


<commit_before># Copyright 2013-2020 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)

from spack import *

class Libtool(AutotoolsPackage, GNUMirrorPackage):
    """libtool -- library building part of autotools."""

    homepage = 'https://www.gnu.org/software/libtool/'
    gnu_mirror_path = "libtool/libtool-2.4.2.tar.gz"

    version('develop', git='https://git.savannah.gnu.org/git/libtool.git',
            branch='master', submodules=True)
    version('2.4.6', sha256='e3bd4d5d3d025a36c21dd6af7ea818a2afcd4dfc1ea5a17b39d7854bcd0c06e3')
    version('2.4.2', sha256='b38de44862a987293cd3d8dfae1c409d514b6c4e794ebc93648febf9afc38918')

    depends_on('m4@1.4.6:', type='build')
    depends_on('autoconf', type='build', when='@2.4.2,develop')
    depends_on('automake', type='build', when='@2.4.2,develop')
    depends_on('help2man', type='build', when='@2.4.2,develop')
    depends_on('xz', type='build', when='@develop')
    depends_on('texinfo', type='build', when='@develop')

    # Fix parsing of compiler output when collecting predeps and postdeps
    # http://lists.gnu.org/archive/html/bug-libtool/2016-03/msg00003.html
    patch('flag_space.patch', when='@develop')

    build_directory = 'spack-build'

    @when('@2.4.2,develop')
    def autoreconf(self, spec, prefix):
        Executable('./bootstrap')()

    def _make_executable(self, name):
        return Executable(join_path(self.prefix.bin, name))

    def setup_dependent_build_environment(self, env, dependent_spec):
        env.append_path('ACLOCAL_PATH', self.prefix.share.aclocal)

    def setup_dependent_package(self, module, dependent_spec):
        # Automake is very likely to be a build dependency, so we add
        # the tools it provides to the dependent module. Some build
        # systems differentiate between BSD libtool (e.g., Darwin) and
        # GNU libtool, so also add 'glibtool' and 'glibtoolize' to the
        # list of executables. See Homebrew:
        # https://github.com/Homebrew/homebrew-core/blob/master/Formula/libtool.rb
        executables = ['libtoolize', 'libtool', 'glibtoolize', 'glibtool']
        for name in executables:
            setattr(module, name, self._make_executable(name))

    @run_after('install')
    def post_install(self):
        # Some platforms name GNU libtool and GNU libtoolize
        # 'glibtool' and 'glibtoolize', respectively, to differentiate
        # them from BSD libtool and BSD libtoolize. On these BSD
        # platforms, build systems sometimes expect to use the assumed
        # GNU commands glibtool and glibtoolize instead of the BSD
        # variant; this happens frequently, for instance, on Darwin
        symlink(join_path(self.prefix.bin, 'libtool'),
                join_path(self.prefix.bin, 'glibtool'))
        symlink(join_path(self.prefix.bin, 'libtoolize'),
                join_path(self.prefix.bin, 'glibtoolize'))
<commit_msg>Libtool: add spack external find support (#16691)<commit_after># Copyright 2013-2020 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)

import os
import re

class Libtool(AutotoolsPackage, GNUMirrorPackage):
    """libtool -- library building part of autotools."""

    homepage = 'https://www.gnu.org/software/libtool/'
    gnu_mirror_path = "libtool/libtool-2.4.2.tar.gz"

    version('develop', git='https://git.savannah.gnu.org/git/libtool.git',
            branch='master', submodules=True)
    version('2.4.6', sha256='e3bd4d5d3d025a36c21dd6af7ea818a2afcd4dfc1ea5a17b39d7854bcd0c06e3')
    version('2.4.2', sha256='b38de44862a987293cd3d8dfae1c409d514b6c4e794ebc93648febf9afc38918')

    depends_on('m4@1.4.6:', type='build')
    depends_on('autoconf', type='build', when='@2.4.2,develop')
    depends_on('automake', type='build', when='@2.4.2,develop')
    depends_on('help2man', type='build', when='@2.4.2,develop')
    depends_on('xz', type='build', when='@develop')
    depends_on('texinfo', type='build', when='@develop')

    # Fix parsing of compiler output when collecting predeps and postdeps
    # http://lists.gnu.org/archive/html/bug-libtool/2016-03/msg00003.html
    patch('flag_space.patch', when='@develop')

    build_directory = 'spack-build'

    executables = ['^g?libtool(ize)?$']

    @classmethod
    def determine_version(cls, exe):
        output = Executable(exe)('--version', output=str, error=os.devnull)
        match = re.search(r'\(GNU libtool\)\s+(\S+)', output)
        return match.group(1) if match else None

    @when('@2.4.2,develop')
    def autoreconf(self, spec, prefix):
        Executable('./bootstrap')()

    def _make_executable(self, name):
        return Executable(join_path(self.prefix.bin, name))

    def setup_dependent_build_environment(self, env, dependent_spec):
        env.append_path('ACLOCAL_PATH', self.prefix.share.aclocal)

    def setup_dependent_package(self, module, dependent_spec):
        # Automake is very likely to be a build dependency, so we add
        # the tools it provides to the dependent module. Some build
        # systems differentiate between BSD libtool (e.g., Darwin) and
        # GNU libtool, so also add 'glibtool' and 'glibtoolize' to the
        # list of executables. See Homebrew:
        # https://github.com/Homebrew/homebrew-core/blob/master/Formula/libtool.rb
        executables = ['libtoolize', 'libtool', 'glibtoolize', 'glibtool']
        for name in executables:
            setattr(module, name, self._make_executable(name))

    @run_after('install')
    def post_install(self):
        # Some platforms name GNU libtool and GNU libtoolize
        # 'glibtool' and 'glibtoolize', respectively, to differentiate
        # them from BSD libtool and BSD libtoolize. On these BSD
        # platforms, build systems sometimes expect to use the assumed
        # GNU commands glibtool and glibtoolize instead of the BSD
        # variant; this happens frequently, for instance, on Darwin
        symlink(join_path(self.prefix.bin, 'libtool'),
                join_path(self.prefix.bin, 'glibtool'))
        symlink(join_path(self.prefix.bin, 'libtoolize'),
                join_path(self.prefix.bin, 'glibtoolize'))
<|endoftext|>