import unittest
from unittest.mock import call

import multiprocessing as mp
from sharedmock.asserters import assert_calls_equal
from sharedmock.mock import SharedMock


def get_mock_return_value(result_queue, mock):
    """
    Picklable function used to test mock calls in subprocesses
    """
    return_value = mock()
    result_queue.put(return_value)


def ignore_mock(result_queue, mock):
    """
    Picklable function used to test mock calls in subprocesses
    """
    result_queue.put(None)  # to unblock caller process


def call_mock_once(result_queue, mock):
    """
    Picklable function used to test mock calls in subprocesses
    """
    mock()
    result_queue.put(None)  # to unblock caller process


def call_mock_thrice(result_queue, mock):
    """
    Picklable function used to test mock calls in subprocesses
    """
    mock()
    mock()
    mock()
    result_queue.put(None)  # to unblock caller process


def call_mock_with_args(result_queue, mock, *args, **kwargs):
    """
    Picklable function used to test mock calls in subprocesses
    """
    mock(*args, **kwargs)
    result_queue.put(None)  # to unblock caller process


class TestSharedMock(unittest.TestCase):

    def call_function_in_subprocess(self, function, args, kwargs={}):
        result_queue = mp.Queue()
        subprocess = mp.Process(target=function,
                                args=(result_queue, *args),
                                kwargs=kwargs)
        subprocess.start()
        subprocess.join()
        subprocess.terminate()

        result = result_queue.get()
        return result

    def test__instantiation__expectZeroCallCount(self):
        mock = SharedMock()

        actual_call_count = mock.call_count
        expected_call_count = 0
        self.assertEqual(expected_call_count, actual_call_count)

    def test__instantiation__expectNoneReturnValue(self):
        mock = SharedMock()

        actual_return_value = mock()
        expected_return_value = None
        self.assertEqual(expected_return_value, actual_return_value)

    def test__instantiation__expectEmptyMockCalls(self):
        mock = SharedMock()

        actual_mock_calls = mock.mock_calls