import unittest
import imp
import sys
import importlib
from unittest import mock
import os
from unittest.mock import MagicMock
import requests
from mock import Mock,call

sys.modules['checks'] = __import__('mock_checks')

spec = importlib.util.spec_from_file_location("AlfSolrCheck", os.path.abspath('files/default/datadog/agents/alfSolr.py'))
agent_module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(agent_module)

def mocked_requests_get200(*args, **kwargs):

    class MockResponse:
        def __init__(self, json_data, status_code):
            self.json_data = json_data
            self.status_code = status_code

        def json(self):
            return self.json_data

    return MockResponse({"Summary":
    {"alfresco":
        {"Approx transaction indexing time remaining":"1 Seconds",
        "Approx transactions remaining":2,
        "TX Lag":"3 s"
        },
    "archive":
        {"Approx transaction indexing time remaining":"4 Seconds",
        "Approx transactions remaining":5,
        "TX Lag":"6 s"
        }
        }
        },
     200)

def mocked_requests_get400(*args, **kwargs):
    class MockResponse:
        def __init__(self, json_data, status_code):
            self.json_data = json_data
            self.status_code = status_code

        def json(self):
            return self.json_data

    return MockResponse({"Summary":
    {"alfresco":
        {"Approx transaction indexing time remaining":"1 Seconds",
        "Approx transactions remaining":2,
        "TX Lag":"3 s"
        },
    "archive":
        {"Approx transaction indexing time remaining":"4 Seconds",
        "Approx transactions remaining":5,
        "TX Lag":"6 s"
        }
        }
        },
     404)

def mocked_requests_get_empty_json(*args, **kwargs):
    class MockResponse:
        def __init__(self, json_data, status_code):
            self.json_data = json_data
            self.status_code = status_code

        def json(self):
            return self.json_data

    return MockResponse({},200)

def mocked_requests_get_timeout(*args, **kwargs):
    raise requests.exceptions.Timeout

def mocked_requests_get_connection_error(*args, **kwargs):
    raise requests.exceptions.ConnectionError

def mocked_requests_get_value_error(*args, **kwargs):
    raise ValueError

# Our test case class
class TestAlfSolrCheck(unittest.TestCase):

    instance = {}
    instance['host']='localhost'
    instance['port']='8070'
    instance['timeout']='5'
    alfSolrCheck = agent_module.AlfSolrCheck()

    @mock.patch('requests.get', side_effect=mocked_requests_get200)
    def test_check_200(self, mock_get):
        self.alfSolrCheck.gauge = MagicMock()
        self.alfSolrCheck.check(self.instance)
        self.alfSolrCheck.gauge.assert_has_calls([
            call('solr4.tracker.alfresco.approx.txns.remaining', 2, tags=[self.alfSolrCheck.SOLR4]),
            call('solr4.tracker.archive.approx.txns.remaining', 5, tags=[self.alfSolrCheck.SOLR4]),
            call('solr4.tracker.alfresco.approx.indexing.time.remaining', 1, tags=[self.alfSolrCheck.SOLR4]),
            call('solr4.tracker.archive.approx.indexing.time.remaining', 4, tags=[self.alfSolrCheck.SOLR4]),
            call('solr4.tracker.alfresco.lag', 3, tags=[self.alfSolrCheck.SOLR4]),
            call('solr4.tracker.archive.lag', 6, tags=[self.alfSolrCheck.SOLR4])
            ])

    @mock.patch('requests.get', side_effect=mocked_requests_get400)
    def test_check_400(self, mock_get):
        self.alfSolrCheck.status_code_event = MagicMock()
        self.alfSolrCheck.check(self.instance)
        assert self.alfSolrCheck.status_code_event.called

    @mock.patch('requests.get', side_effect=mocked_requests_get_empty_json)
    def test_check_empty_json(self, mock_get):
        self.alfSolrCheck.jsonerror_event = MagicMock()
        self.alfSolrCheck.check(self.instance)
        assert self.alfSolrCheck.jsonerror_event.called

    @mock.patch('requests.get', side_effect=mocked_requests_get_timeout)
    def test_check_timeout(self, mock_get):
        self.alfSolrCheck.timeout_event = MagicMock()
        self.alfSolrCheck.check(self.instance)
        assert self.alfSolrCheck.timeout_event.called

    @mock.patch('requests.get', side_effect=mocked_requests_get_connection_error)
    def test_check_connection_error(self, mock_get):
        self.alfSolrCheck.connectionerror_event = MagicMock()
        self.alfSolrCheck.check(self.instance)
        assert self.alfSolrCheck.connectionerror_event.called

    @mock.patch('requests.get', side_effect=mocked_requests_get_value_error)
    def test_check_value_error(self, mock_get):
        self.alfSolrCheck.jsonerror_event = MagicMock()
        self.alfSolrCheck.check(self.instance)
        assert self.alfSolrCheck.jsonerror_event.called

    # if host is missing it should not go through
    @mock.patch('requests.get', side_effect=mocked_requests_get200)
    def test_check_no_host(self, mock_get):
        alfSolrCheck = agent_module.AlfSolrCheck()
        new_instance = {}
        self.alfSolrCheck.log.error = MagicMock()
        self.alfSolrCheck.check(new_instance)
        assert self.alfSolrCheck.log.error.called
        self.alfSolrCheck.gauge.assert_not_called

    # if port is missing it should not go through
    @mock.patch('requests.get', side_effect=mocked_requests_get200)
    def test_check_no_port(self, mock_get):
        alfSolrCheck = agent_module.AlfSolrCheck()
        new_instance = {}
        new_instance['host']='localhost'
        new_instance['timeout']='5'
        self.alfSolrCheck.log.error = MagicMock()
        self.alfSolrCheck.check(new_instance)
        assert self.alfSolrCheck.log.error.called
        self.alfSolrCheck.gauge.assert_not_called

    def test_getSecFromTransactionString(self):

        val= 2
        val_str = str(val)
        res = self.alfSolrCheck.getSecFromTransactionString(val_str+" Seconds")
        self.assertEqual(res,val*self.alfSolrCheck.timeMap["Second"])

        res = self.alfSolrCheck.getSecFromTransactionString(val_str+" Minutes")
        self.assertEqual(res,val*self.alfSolrCheck.timeMap["Minute"])

        res = self.alfSolrCheck.getSecFromTransactionString(val_str+" Hours")
        self.assertEqual(res,val*self.alfSolrCheck.timeMap["Hour"])

        res = self.alfSolrCheck.getSecFromTransactionString(val_str+" Days")
        self.assertEqual(res,val*self.alfSolrCheck.timeMap["Day"])

        res = self.alfSolrCheck.getSecFromTransactionString(val_str+" Months")
        self.assertEqual(res,val*self.alfSolrCheck.timeMap["Month"])

        res = self.alfSolrCheck.getSecFromTransactionString(val_str+" Years")
        self.assertEqual(res,val*self.alfSolrCheck.timeMap["Year"])

        #not a valid response return 0
        res = self.alfSolrCheck.getSecFromTransactionString(val_str)
        self.assertEqual(res,0)

        #not a valid response return 0
        res = self.alfSolrCheck.getSecFromTransactionString("not a number")
        self.assertEqual(res,0)

    def test_getSecFromLagString(self):

        res = self.alfSolrCheck.getSecFromLagString("1 s")
        self.assertEqual(res,1)

        #not a valid response return 0
        res = self.alfSolrCheck.getSecFromLagString("2")
        self.assertEqual(res,0)

        #not a valid response return 0
        res = self.alfSolrCheck.getSecFromLagString("not a number")
        self.assertEqual(res,0)


if __name__ == '__main__':
    unittest.main()
