from alphatwirl.loop import MPEventLoopRunner
import unittest
import os

##__________________________________________________________________||
class MockCommunicationChannel(object):
    def __init__(self):
        self.eventLoops = [ ]
        self.resultsToReceive = [ ]

    def put(self, task):
        eventLoop = task
        self.eventLoops.append(eventLoop)

    def receive(self):
        return self.resultsToReceive

##__________________________________________________________________||
class MockResult(object): pass

##__________________________________________________________________||
class MockEventLoop(object): pass

##__________________________________________________________________||
class TestMPEventLoopRunner(unittest.TestCase):

    def test_repr(self):
        communicationChannel = MockCommunicationChannel()
        obj = MPEventLoopRunner(communicationChannel)
        repr(obj)

    def test_begin_end(self):
        communicationChannel = MockCommunicationChannel()
        obj = MPEventLoopRunner(communicationChannel)
        obj.begin()
        obj.end()

    def test_bgin_run_end(self):
        communicationChannel = MockCommunicationChannel()
        obj = MPEventLoopRunner(communicationChannel)
        obj.begin()

        eventLoop1 = MockEventLoop()
        obj.run(eventLoop1)

        eventLoop2 = MockEventLoop()
        obj.run(eventLoop2)

        self.assertEqual([eventLoop1, eventLoop2], communicationChannel.eventLoops)

        result1 = MockResult()
        result2 = MockResult()
        communicationChannel.resultsToReceive = [result1, result2]

        self.assertEqual([result1, result2], obj.end())

    # @unittest.skip("skip because of logging. assertLogs can be used here for Python 3.4")
    def test_wrong_number_or_results(self):
        communicationChannel = MockCommunicationChannel()
        obj = MPEventLoopRunner(communicationChannel)
        obj.begin()

        eventLoop1 = MockEventLoop()
        obj.run(eventLoop1)

        eventLoop2 = MockEventLoop()
        obj.run(eventLoop2)

        self.assertEqual([eventLoop1, eventLoop2], communicationChannel.eventLoops)

        result1 = MockResult()
        result2 = MockResult()
        communicationChannel.resultsToReceive = [result1]

        self.assertEqual([result1], obj.end())

##__________________________________________________________________||

# Tai Sakuma <tai.sakuma@gmail.com>
import logging
import pytest

try:
    import unittest.mock as mock
except ImportError:
    import mock

from alphatwirl.loop import MPEventLoopRunner

##__________________________________________________________________||
@pytest.fixture()
def communicationChannel():
    return mock.Mock(name='communicationChannel')

@pytest.fixture()
def obj(communicationChannel):
    return MPEventLoopRunner(communicationChannel)

##__________________________________________________________________||
def test_repr(obj):
    repr(obj)

def test_begin_end(obj, communicationChannel):
    obj.begin()
    communicationChannel.receive.return_value = [ ]
    obj.end()

def test_begin_run_end(obj, communicationChannel):
    obj.begin()

    eventLoop1 = mock.Mock(name='eventLoop1')
    obj.run(eventLoop1)

    eventLoop2 = mock.Mock(name='eventLoop2')
    obj.run(eventLoop2)

    assert [mock.call(eventLoop1), mock.call(eventLoop2)] == communicationChannel.put.call_args_list

    result1 = mock.Mock(name='result1')
    result2 = mock.Mock(name='result2')
    communicationChannel.receive.return_value = [result1, result2]
    assert [result1, result2] == obj.end()

def test_wrong_number_or_results(obj, communicationChannel, caplog):
    obj.begin()

    eventLoop1 = mock.Mock(name='eventLoop1')
    obj.run(eventLoop1)

    eventLoop2 = mock.Mock(name='eventLoop2')
    obj.run(eventLoop2)

    result1 = mock.Mock(name='result1')
    result2 = mock.Mock(name='result2')
    communicationChannel.receive.return_value = [result1]

    with caplog.at_level(logging.WARNING, logger = 'alphatwirl'):
        results = obj.end()

    assert [result1] == results

    assert len(caplog.records) == 1
    assert caplog.records[0].levelname == 'WARNING'
    assert 'MPEventLoopRunner' in caplog.records[0].name
    assert 'too few results received' in caplog.records[0].msg

##__________________________________________________________________||

replace unittest with pytest, add test for logging