"""Unit tests of MQProducer interface in the DIRAC.Resources.MessageQueue.MProducerQ
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import unittest
from DIRAC import S_OK
from DIRAC.Resources.MessageQueue.MQProducer import MQProducer
from DIRAC.Resources.MessageQueue.MQConnectionManager import MQConnectionManager
from DIRAC.Resources.MessageQueue.MQConnector import MQConnector


class FakeMQConnector(MQConnector):
  def __init__(self, params={}):
    super(FakeMQConnector, self).__init__()

  def disconnect(self):
    return S_OK("FakeMQConnection disconnecting")

  def get(self, destination=''):
    return "FakeMQConnection getting message"

  def put(self, message, parameters=None):
    return S_OK("FakeMQConnection sending message: " + str(message))


class TestMQProducer(unittest.TestCase):
  def setUp(self):
    self.maxDiff = None  # To show full difference between structures in  case of error
    dest = {}
    dest.update({'/queue/FakeQueue': ['producer4', 'producer2']})
    dest4 = {'/queue/test3': ['producer1', 'consumer2', 'consumer3', 'consumer4']}
    conn1 = {'MQConnector': FakeMQConnector(), 'destinations': dest}
    conn2 = {'MQConnector': FakeMQConnector(), 'destinations': dest4}
    storage = {'fake.cern.ch': conn1, 'testdir.blabla.ch': conn2}
    self.myManager = MQConnectionManager(connectionStorage=storage)

  def tearDown(self):
    pass


class TestMQProducer_put(TestMQProducer):
  def test_success(self):
    producer = MQProducer(mqManager=self.myManager, mqURI="fake.cern.ch::Queues::FakeQueue", producerId='producer4')
    result = producer.put("wow!")
    self.assertTrue(result['OK'])
    self.assertEqual(result['Value'], "FakeMQConnection sending message: wow!")

  def test_failure(self):
    producer = MQProducer(mqManager=self.myManager, mqURI="bad.cern.ch::Queues::FakeQueue", producerId='producer4')
    result = producer.put("wow!")
    self.assertFalse(result['OK'])


class TestMQProducer_close(TestMQProducer):
  def test_success(self):
    producer = MQProducer(mqManager=self.myManager, mqURI="fake.cern.ch::Queues::FakeQueue", producerId='producer4')
    result = producer.close()
    self.assertTrue(result['OK'])
    # producer is still able to sent cause the connection is still active (producer2 is connected)
    result = producer.put("wow!")
    self.assertTrue(result['OK'])

  def test_failure(self):
    producer = MQProducer(mqManager=self.myManager, mqURI="fake.cern.ch::Queues::FakeQueue", producerId='producer4')
    result = producer.close()
    self.assertTrue(result['OK'])
    result = producer.close()
    self.assertFalse(result['OK'])
    self.assertEqual(
        result['Message'],
        'MQ connection failure ( 1142 : Failed to stop the connection!The messenger producer4 does not exist!)')

  def test_failure2(self):
    producer = MQProducer(mqManager=self.myManager, mqURI="fake.cern.ch::Queues::FakeQueue", producerId='producer4')
    producer2 = MQProducer(mqManager=self.myManager, mqURI="fake.cern.ch::Queues::FakeQueue", producerId='producer2')
    result = producer.close()
    self.assertTrue(result['OK'])
    result = producer.close()
    self.assertFalse(result['OK'])
    self.assertEqual(
        result['Message'],
        'MQ connection failure ( 1142 : Failed to stop the connection!The messenger producer4 does not exist!)')
    result = producer2.close()
    self.assertTrue(result['OK'])
    result = producer2.close()
    self.assertFalse(result['OK'])
    self.assertEqual(
        result['Message'],
        'MQ connection failure ( 1142 : Failed to stop the connection!The messenger producer2 does not exist!)')
    # connection does not exist so put will not work
    result = producer.put("wow!")
    self.assertFalse(result['OK'])
    self.assertEqual(result['Message'], 'Failed to get the MQConnector!')


if __name__ == '__main__':
  suite = unittest.defaultTestLoader.loadTestsFromTestCase(TestMQProducer)
  suite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(TestMQProducer_put))
  suite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(TestMQProducer_close))
  testResult = unittest.TextTestRunner(verbosity=2).run(suite)
