<commit_before># FLOC-1549

# """
# Tests for ``flocker.common._thread``.
# """

# Test that methods of an implementation of some dummy interface get run using
# the threadpool supplied.  Use a fake thread pool.<commit_msg>A stab at an ``auto_threaded`` test suite.<commit_after># Copyright ClusterHQ Inc.  See LICENSE file for details.

# """
# Tests for ``flocker.common._thread``.
# """

from zope.interface import Interface, implementer

from twisted.trial.unittest import SynchronousTestCase, TestCase
from twisted.python.failure import Failure
from twisted.python.threadpool import ThreadPool

from pyrsistent import PRecord, field

from .. import auto_threaded


class IStub(Interface):
    def method(self, a, b, c):
        pass


@implementer(IStub)
class Spy(object):
    def __init__(self):
        self.calls = []

    def method(self, a, b, c):
        self.calls.append((a, b, c))
        return a + b + c


@auto_threaded(IStub, "reactor", "provider", "threadpool")
class AsyncSpy(PRecord):
    reactor = field()
    provider = field()
    threadpool = field()


class NonThreadPool(object):
    def callInThreadWithCallback(self, onResult, func, *args, **kw):
        try:
            result = func(*args, **kw)
        except:
            onResult(Failure())
        else:
            onResult(result)


class AutoThreadedTests(SynchronousTestCase):
    """
    Tests for ``flocker.common.auto_threaded``.
    """
    def setUp(self):
        self.reactor = object()
        self.threadpool = object()
        # Some unique objects that support ``+``
        self.a = [object()]
        self.b = [object()]
        self.c = [object()]
        self.spy = Spy()
        self.async_spy = AsyncSpy(
            reactor=self.reactor, threadpool=self.threadpool, provider=self.spy
        )

    def test_called_with_same_arguments(self):
        """
        A class can be decorated with ``auto_threaded`` with an interface and a
        provider of that interface.  When methods from the interface are called
        on instances of the class, the corresponding method is called with the
        same arguments on the provider of the interface.
        """
        self.async_spy.method(self.a, c=self.c, b=self.b)
        self.assertEqual([(self.a, self.b, self.c)], self.spy.calls)

    def test_success_result(self):
        """
        When methods from the interface are called on instances of the class, a
        ``Deferred`` is returned which fires with the result of the call to the
        corresponding method on the provider of the interface.
        """
        args = (self.a, self.b, self.c)
        result = self.successResultOf(self.async_spy.method(*args))
        self.assertEqual(self.spy.method(*args), result)

    def test_failure_result(self):
        """
        When the corresponding method on the provider of the interface raises
        an exception, the ``Deferred`` fires with a ``Failure`` representing
        that exception.
        """
        self.failureResultOf(
            self.async_spy.method(None, None, None),
            TypeError
        )

    def test_called_in_threadpool(self):
        """
        The corresponding method of the provider of the interface is called in
        a thread using the threadpool specified to ``auto_threaded``.
        """
        self.async_spy.method(self.a, self.b, self.c)


class AutoThreadedIntegrationTests(TestCase):
    """
    Tests for ``auto_threaded`` in combination with a real thread pool,
    ``twisted.python.threads.ThreadPool``.
    """
    def test_integration(self):
        """
        ``auto_threaded`` works with ``twisted.python.threads.ThreadPool``.
        """
        from twisted.internet import reactor

        threadpool = ThreadPool(minthreads=1, name=self.id())
        threadpool.start()
        self.addCleanup(threadpool.stop)

        spy = Spy()
        async_spy = AsyncSpy(
            reactor=reactor, threadpool=threadpool, provider=spy
        )

        a = [object()]
        b = [object()]
        c = [object()]
        result = async_spy.method(a, b, c)
        result.addCallback(self.assertEqual, spy.method(a, b, c))
        return result
{'fraction_non_alphanumeric': 0.10975609756097561, 'fraction_numerical': 0.0011956001912960307, 'mean_word_length': 2.5752136752136754, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5774725', 'n_tokens_mistral': 1214, 'n_tokens_neox': 1201, 'n_words': 353}