# -*- coding: utf-8 -*-
#
# Copyright 2012 Canonical Ltd.
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 3, as published
# by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranties of
# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
# PURPOSE.  See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program.  If not, see <http://www.gnu.org/licenses/>.
#
# In addition, as a special exception, the copyright holders give
# permission to link the code of portions of this program with the
# OpenSSL library under certain conditions as described in each
# individual source file, and distribute linked combinations
# including the two.
# You must obey the GNU General Public License in all respects
# for all of the code used other than OpenSSL.  If you modify
# file(s) with this exception, you may extend this exception to your
# version of the file(s), but you are not obligated to do so.  If you
# do not wish to do so, delete this exception statement from your
# version.  If you delete this exception statement from all source
# files in the program, then also delete it here.
"""Tests for the platform specific functions (for Windows)."""

import thread

from twisted.internet import defer
from twisted.trial.unittest import TestCase

from ubuntu_kylin_sso.utils.qtwisted import qtDeferToThread


class FakeException(Exception):
    """A Fake exception."""


class QtDeferToThreadTestCase(TestCase):
    """A Qt-based implementation of deferToThread."""

    @defer.inlineCallbacks
    def test_executes_function_returns_result(self):
        """The passed function is executed and returns the result."""

        def fake_operation(first, second="world!"):
            """Testing positional and keyword arguments."""
            return first + " " + second

        result = yield qtDeferToThread(fake_operation, "hola", second="mundo!")
        self.assertEqual(result, "hola mundo!")

    @defer.inlineCallbacks
    def test_exceptions_become_failures(self):
        """Any exception while running the function becomes a failure."""

        def fake_raise():
            """Throw the fake exception."""
            raise FakeException

        yield self.assertFailure(qtDeferToThread(fake_raise), FakeException)

    @defer.inlineCallbacks
    def test_function_runs_in_new_thread(self):
        """The concerned function is run in a different thread."""

        def inner_function():
            """This should be run in a different thread."""
            return thread.get_ident()

        other_thread_id = yield qtDeferToThread(inner_function)
        this_thread_id = thread.get_ident()
        self.assertNotEqual(this_thread_id, other_thread_id)
