# Copyright (c) 2020, eQualit.ie inc.
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.


import os
import baskerville
import unittest
from unittest import mock

import yaml
from baskerville.models.config import BaskervilleConfig, MetricsConfig
from baskerville.util.enums import RunType

from tests.unit.baskerville_tests.helpers.utils import get_default_data_path


class TestBaskervilleAnalyticsEngine(unittest.TestCase):
    def setUp(self):
        self.patcher = mock.patch.object(BaskervilleConfig, 'validate')
        self.dbpatcher = mock.patch(
            'baskerville.util.baskerville_tools.BaskervilleDBTools'
        )
        self.mock_baskerville_tools = self.dbpatcher.start()
        with open(
                f'{get_default_data_path()}/conf/test_baskerville_conf.yaml'
        ) as f:
            self.test_config = yaml.load(f)
        log_path = f'{os.path.dirname(baskerville.__file__)}/logs/' \
                   f'test_base.log'
        self.mock_baskerville_config = self.patcher.start()
        self.test_config['engine']['log_level'] = 'DEBUG'
        self.test_config['engine']['logpath'] = log_path

    def tearDown(self):
        self.patcher.stop()
        self.dbpatcher.stop()

    def test_instance(self, ):
        from baskerville.models.engine import BaskervilleAnalyticsEngine
        engine = BaskervilleAnalyticsEngine(
            RunType.rawlog, self.test_config
        )
        self.assertTrue(engine.run_type == RunType.rawlog)

    def test__set_up_pipeline_manual_els_spark(self):
        from baskerville.models.pipelines import RawLogPipeline
        with mock.patch.object(
                RawLogPipeline, '__init__'
        ) as mock_pipeline:
            from baskerville.models.engine import BaskervilleAnalyticsEngine
            mock_pipeline.return_value = None
            engine = BaskervilleAnalyticsEngine(
                RunType.rawlog, self.test_config
            )
            self.assertTrue(engine.run_type == RunType.rawlog)

            engine.config.engine.manual.host = 'test'
            engine.config.engine.use_spark = True
            p = engine._set_up_pipeline()

            mock_pipeline.assert_called_once()
            self.assertTrue(isinstance(p, RawLogPipeline))

    def test__set_up_pipeline_manual_raw_logs_path_spark(self):
        from baskerville.models.pipelines import RawLogPipeline
        with mock.patch.object(
                RawLogPipeline, '__init__'
        ) as mock_pipeline:
            from baskerville.models.engine import BaskervilleAnalyticsEngine
            mock_pipeline.return_value = None
            engine = BaskervilleAnalyticsEngine(
                RunType.rawlog, self.test_config
            )
            self.assertTrue(engine.run_type == RunType.rawlog)
            engine.config.engine.manual.host = None
            engine.config.engine.manual.raw_logs_path = 'some_path'
            engine.config.engine.manual.chunk_size = 0
            engine.config.engine.use_spark = True
            p = engine._set_up_pipeline()
            mock_pipeline.assert_called_once()
            self.assertTrue(isinstance(p, RawLogPipeline))

    def test__set_up_pipeline_auto_spark(self):
        from baskerville.models.pipelines import KafkaPipeline
        with mock.patch.object(
                KafkaPipeline, '__init__'
        ) as mock_pipeline:
            from baskerville.models.engine import BaskervilleAnalyticsEngine
            mock_pipeline.return_value = None
            engine = BaskervilleAnalyticsEngine(
                RunType.kafka, self.test_config
            )
            self.assertTrue(engine.run_type == RunType.kafka)

            engine.config.engine.use_spark = True
            p = engine._set_up_pipeline()

            mock_pipeline.assert_called_once()
            self.assertTrue(isinstance(p, KafkaPipeline))

    def test_register_performance_stats(self):
        from baskerville.models.engine import BaskervilleAnalyticsEngine
        with mock.patch.object(
                BaskervilleAnalyticsEngine, '_set_up_pipeline'
        ) as _:
            engine = BaskervilleAnalyticsEngine(
                RunType.kafka, self.test_config
            )

            mock_pipeline = mock.MagicMock()
            mock_feature1 = mock.MagicMock()
            mock_feature2 = mock.MagicMock()

            mock_feature1.feature_name = 'mock_feature1'
            mock_feature2.feature_name = 'mock_feature2'

            mock_feature1.compute = lambda a: a
            mock_feature2.compute = lambda a: a

            mock_pipeline.feature_manager = mock.MagicMock()
            mock_pipeline.feature_manager.active_features = [
                mock_feature1, mock_feature2
            ]
            mock_pipeline.test_method_name_1.__name__ = 'test_method_name_1'
            mock_pipeline.test_method_name_2.__name__ = 'test_method_name_2'
            mock_pipeline.request_set_cache.test_method_name_3.__name__ = \
                'test_method_name_3'
            mock_pipeline.request_set_cache.test_method_name_4.__name__ = \
                'test_method_name_4'

            engine.pipeline = mock_pipeline

            metrics = {
                'performance': {
                    'pipeline': [
                        'test_method_name_1', 'test_method_name_2'
                    ],
                    'request_set_cache': [
                        'test_method_name_3', 'test_method_name_4'
                    ],
                    'features': True,
                }
            }
            engine.config.engine.metrics = MetricsConfig(metrics)
            performance_stats = engine._register_performance_stats()

            self.assertTrue(f'{performance_stats._prefix}timer_for_pipeline_test_method_name_1'
                            in performance_stats.registry)
            self.assertTrue(f'{performance_stats._prefix}timer_for_pipeline_test_method_name_2'
                            in performance_stats.registry)
            self.assertTrue(f'{performance_stats._prefix}timer_for_request_set_cache_test_method_name_3'
                            in performance_stats.registry)
            self.assertTrue(f'{performance_stats._prefix}timer_for_request_set_cache_test_method_name_4'
                            in performance_stats.registry)

            self.assertTrue(
                f'{performance_stats._prefix}timer_for_feature_'
                f'{mock_feature1.feature_name}'
                in performance_stats.registry
            )
            self.assertTrue(
                f'{performance_stats._prefix}timer_for_feature_'
                f'{mock_feature2.feature_name}'
                in performance_stats.registry
            )

    def test_run(self):
        from baskerville.models.engine import BaskervilleAnalyticsEngine
        with mock.patch.object(
                BaskervilleAnalyticsEngine, '_set_up_pipeline'
        ) as mock__set_up_pipeline:
            with mock.patch.object(
                    BaskervilleAnalyticsEngine, '_register_performance_stats'
            ) as mock_register_performance_stats:
                pipeline = mock.MagicMock()
                mock__set_up_pipeline.return_value = pipeline
                mock_register_performance_stats.return_value = \
                    'should return a performance_stats instance'
                metrics = {
                    'performance': True  # completely mocked just to step into
                    # the register_performance_stats step
                }

                engine = BaskervilleAnalyticsEngine(
                    RunType.kafka, self.test_config, register_metrics=False
                )
                engine.config.engine.metrics = MetricsConfig(metrics)
                engine.run()

                mock__set_up_pipeline.assert_called_once()
                mock_register_performance_stats.assert_not_called()
                pipeline.run.assert_called_once()
                self.assertTrue(
                    engine.performance_stats is None
                )

    def test_run_register_metrics(self):
        from baskerville.models.engine import BaskervilleAnalyticsEngine
        with mock.patch.object(
                BaskervilleAnalyticsEngine, '_set_up_pipeline'
        ) as mock__set_up_pipeline:
            with mock.patch.object(
                    BaskervilleAnalyticsEngine, '_register_performance_stats'
            ) as mock_register_performance_stats:
                pipeline = mock.MagicMock()
                mock__set_up_pipeline.return_value = pipeline
                mock_register_performance_stats.return_value = \
                    'should return a performance_stats instance'
                metrics = {
                    'performance': True  # completely mocked just to step into
                    # the register_performance_stats step
                }

                engine = BaskervilleAnalyticsEngine(
                    RunType.kafka, self.test_config, register_metrics=True
                )
                engine.config.engine.metrics = MetricsConfig(metrics)
                engine.run()

                mock__set_up_pipeline.assert_called_once()
                mock_register_performance_stats.assert_called_once()
                pipeline.run.assert_called_once()
                self.assertTrue(engine.performance_stats == 'should return a performance_stats instance')

    def test_finish_up(self):
        pass

# Copyright (c) 2020, eQualit.ie inc.
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.


import os
import baskerville
import unittest
from unittest import mock

import yaml
from baskerville.models.config import BaskervilleConfig, MetricsConfig
from baskerville.util.enums import RunType

from tests.unit.baskerville_tests.helpers.utils import get_default_data_path


class TestBaskervilleAnalyticsEngine(unittest.TestCase):
    def setUp(self):
        self.patcher = mock.patch.object(BaskervilleConfig, 'validate')
        self.dbpatcher = mock.patch(
            'baskerville.util.baskerville_tools.BaskervilleDBTools'
        )
        self.mock_baskerville_tools = self.dbpatcher.start()
        with open(
                f'{get_default_data_path()}/conf/test_baskerville_conf.yaml'
        ) as f:
            self.test_config = yaml.load(f)
        log_path = f'{os.path.dirname(baskerville.__file__)}/logs/' \
                   f'test_base.log'
        self.mock_baskerville_config = self.patcher.start()
        self.test_config['engine']['log_level'] = 'DEBUG'
        self.test_config['engine']['logpath'] = log_path

    def tearDown(self):
        self.patcher.stop()
        self.dbpatcher.stop()

    def test_instance(self, ):
        from baskerville.models.engine import BaskervilleAnalyticsEngine
        engine = BaskervilleAnalyticsEngine(
            RunType.rawlog, self.test_config
        )
        self.assertTrue(engine.run_type == RunType.rawlog)

    def test__set_up_pipeline_manual_els_spark(self):
        from baskerville.models.pipelines import RawLogPipeline
        with mock.patch.object(
                RawLogPipeline, '__init__'
        ) as mock_pipeline:
            from baskerville.models.engine import BaskervilleAnalyticsEngine
            mock_pipeline.return_value = None
            engine = BaskervilleAnalyticsEngine(
                RunType.rawlog, self.test_config
            )
            self.assertTrue(engine.run_type == RunType.rawlog)

            engine.config.engine.manual.host = 'test'
            engine.config.engine.use_spark = True
            p = engine._set_up_pipeline()

            mock_pipeline.assert_called_once()
            self.assertTrue(isinstance(p, RawLogPipeline))

    def test__set_up_pipeline_manual_raw_logs_path_spark(self):
        from baskerville.models.pipelines import RawLogPipeline
        with mock.patch.object(
                RawLogPipeline, '__init__'
        ) as mock_pipeline:
            from baskerville.models.engine import BaskervilleAnalyticsEngine
            mock_pipeline.return_value = None
            engine = BaskervilleAnalyticsEngine(
                RunType.rawlog, self.test_config
            )
            self.assertTrue(engine.run_type == RunType.rawlog)
            engine.config.engine.manual.host = None
            engine.config.engine.manual.raw_logs_path = 'some_path'
            engine.config.engine.manual.chunk_size = 0
            engine.config.engine.use_spark = True
            p = engine._set_up_pipeline()
            mock_pipeline.assert_called_once()
            self.assertTrue(isinstance(p, RawLogPipeline))

    def test__set_up_pipeline_auto_spark(self):
        from baskerville.models.pipelines import KafkaPipeline
        with mock.patch.object(
                KafkaPipeline, '__init__'
        ) as mock_pipeline:
            from baskerville.models.engine import BaskervilleAnalyticsEngine
            mock_pipeline.return_value = None
            engine = BaskervilleAnalyticsEngine(
                RunType.kafka, self.test_config
            )
            self.assertTrue(engine.run_type == RunType.kafka)

            engine.config.engine.use_spark = True
            p = engine._set_up_pipeline()

            mock_pipeline.assert_called_once()
            self.assertTrue(isinstance(p, KafkaPipeline))

    def test_register_performance_stats(self):
        from baskerville.models.engine import BaskervilleAnalyticsEngine
        with mock.patch.object(
                BaskervilleAnalyticsEngine, '_set_up_pipeline'
        ) as _:
            engine = BaskervilleAnalyticsEngine(
                RunType.kafka, self.test_config
            )

            mock_pipeline = mock.MagicMock()
            mock_feature1 = mock.MagicMock()
            mock_feature2 = mock.MagicMock()

            mock_feature1.feature_name = 'mock_feature1'
            mock_feature2.feature_name = 'mock_feature2'

            mock_feature1.compute = lambda a: a
            mock_feature2.compute = lambda a: a

            mock_pipeline.feature_manager = mock.MagicMock()
            mock_pipeline.feature_manager.active_features = [
                mock_feature1, mock_feature2
            ]
            mock_pipeline.test_method_name_1.__name__ = 'test_method_name_1'
            mock_pipeline.test_method_name_2.__name__ = 'test_method_name_2'
            mock_pipeline.request_set_cache.test_method_name_3.__name__ = \
                'test_method_name_3'
            mock_pipeline.request_set_cache.test_method_name_4.__name__ = \
                'test_method_name_4'

            engine.pipeline = mock_pipeline

            metrics = {
                'performance': {
                    'pipeline': [
                        'test_method_name_1', 'test_method_name_2'
                    ],
                    'request_set_cache': [
                        'test_method_name_3', 'test_method_name_4'
                    ],
                    'features': True,
                }
            }
            engine.config.engine.metrics = MetricsConfig(metrics)
            performance_stats = engine._register_performance_stats()

            self.assertTrue(f'{performance_stats._prefix}timer_for_pipeline_test_method_name_1'
                            in performance_stats.registry)
            self.assertTrue(f'{performance_stats._prefix}timer_for_pipeline_test_method_name_2'
                            in performance_stats.registry)
            self.assertTrue(f'{performance_stats._prefix}timer_for_request_set_cache_test_method_name_3'
                            in performance_stats.registry)
            self.assertTrue(f'{performance_stats._prefix}timer_for_request_set_cache_test_method_name_4'
                            in performance_stats.registry)

            self.assertTrue(
                f'{performance_stats._prefix}timer_for_feature_'
                f'{mock_feature1.feature_name}'
                in performance_stats.registry
            )
            self.assertTrue(
                f'{performance_stats._prefix}timer_for_feature_'
                f'{mock_feature2.feature_name}'
                in performance_stats.registry
            )

    def test_run(self):
        from baskerville.models.engine import BaskervilleAnalyticsEngine
        with mock.patch.object(
                BaskervilleAnalyticsEngine, '_set_up_pipeline'
        ) as mock__set_up_pipeline:
            with mock.patch.object(
                    BaskervilleAnalyticsEngine, '_register_performance_stats'
            ) as mock_register_performance_stats:
                pipeline = mock.MagicMock()
                mock__set_up_pipeline.return_value = pipeline
                mock_register_performance_stats.return_value = \
                    'should return a performance_stats instance'
                metrics = {
                    'performance': True  # completely mocked just to step into
                    # the register_performance_stats step
                }

                engine = BaskervilleAnalyticsEngine(
                    RunType.kafka, self.test_config, register_metrics=False
                )
                engine.config.engine.metrics = MetricsConfig(metrics)
                engine.run()

                mock__set_up_pipeline.assert_called_once()
                mock_register_performance_stats.assert_not_called()
                pipeline.run.assert_called_once()
                self.assertTrue(
                    engine.performance_stats is None
                )

    def test_run_register_metrics(self):
        from baskerville.models.engine import BaskervilleAnalyticsEngine
        with mock.patch.object(
                BaskervilleAnalyticsEngine, '_set_up_pipeline'
        ) as mock__set_up_pipeline:
            with mock.patch.object(
                    BaskervilleAnalyticsEngine, '_register_performance_stats'
            ) as mock_register_performance_stats:
                pipeline = mock.MagicMock()
                mock__set_up_pipeline.return_value = pipeline
                mock_register_performance_stats.return_value = \
                    'should return a performance_stats instance'
                metrics = {
                    'performance': True  # completely mocked just to step into
                    # the register_performance_stats step
                }

                engine = BaskervilleAnalyticsEngine(
                    RunType.kafka, self.test_config, register_metrics=True
                )
                engine.config.engine.metrics = MetricsConfig(metrics)
                engine.run()

                mock__set_up_pipeline.assert_called_once()
                mock_register_performance_stats.assert_called_once()
                pipeline.run.assert_called_once()
                self.assertTrue(engine.performance_stats == 'should return a performance_stats instance')

    def test_finish_up(self):
        pass

# Copyright (c) 2020, eQualit.ie inc. # All rights reserved. # # This source code is licensed under the BSD-style license found in the # LICENSE file in the root directory of this source tree. # completely mocked just to step into # the register_performance_stats step # completely mocked just to step into # the register_performance_stats step