# -*- coding: utf-8 -*-
# Moovida - Home multimedia server
# Copyright (C) 2006-2009 Fluendo Embedded S.L. (www.fluendo.com).
# All rights reserved.
#
# This file is available under one of two license agreements.
#
# This file is licensed under the GPL version 3.
# See "LICENSE.GPL" in the root of this distribution including a special
# exception to use Moovida with Fluendo's plugins.
#
# The GPL part of Moovida is also available under a commercial licensing
# agreement from Fluendo.
# See "LICENSE.Moovida" in the root directory of this distribution package
# for details on that license.


# this both should work without problems at all

# things to test:
from elisa.core.utils import defer
from elisa.core.utils.defer import Deferred
from twisted.internet import defer as twisted_defer

from twisted.trial import unittest

class DeferFunctionTesting(unittest.TestCase):

    def testDeffered(self):
        # check if the importet Deferred has the cancel-API
        self.failUnless(hasattr(Deferred(), 'cancel'))
        self.failUnless(hasattr(defer.Deferred(), 'cancel'))

    def testSucceed(self):
        # test if the returned Deferred has the cancel-API
        l = []
        dfr = defer.succeed('Yeah!')
        self.failUnless(hasattr(dfr, 'cancel'))
        dfr.addCallback(l.append)
        self.assertEquals(l[0], "Yeah!")

    def testFail(self):
        # test if the returned Deferred has the cancel-API
        l = []
        dfr = defer.fail(Exception())
        self.failUnless(hasattr(dfr, 'cancel'))
        dfr.addErrback(l.append)
        self.assertEquals(l[0].type, Exception)

        def error_function():
            something

        dfr = None

        try: 
            error_function()
        except:
            dfr = defer.fail()

        self.failUnless(hasattr(dfr, 'cancel'))
        dfr.addErrback(l.append)
        self.assertEquals(l[1].type, NameError)

    def testExecute(self):

        l = []
        # works out
        dfr = defer.execute( lambda x,y,z,foo: (x,y,z,foo) , 
                             'one', 'two', 'three', foo='bar')
        self.failUnless(hasattr(dfr, 'cancel'))
        dfr.addCallback(l.append)
        self.assertEquals(l[0], ('one', 'two', 'three', 'bar'))

        # fails
        dfr = defer.execute( lambda x: y,
                             'yeah', 'yeah', 'yeah', cool=True)
        self.failUnless(hasattr(dfr, 'cancel'))
        dfr.addErrback(l.append)
        self.assertEquals(len(l), 2)


    def testTimeout(self):

        l = []
        dfr = defer.Deferred(canceller=lambda x: x)
        dfr.addErrback(l.append)
        defer.timeout(dfr)
        # we got the right errback
        self.assertEquals(l[0].type, defer.CancelledError)

        # test the compability
        dfr = twisted_defer.Deferred()
        dfr.addErrback(l.append)
        defer.timeout(dfr)
        self.assertEquals(l[1].type, defer.TimeoutError)

    def testCompability(self):
        # test that all given classes and methods of twisted defer are in our
        # defer
        msg = "We miss %s" 
        for item in twisted_defer.__all__:
            self.assertTrue(hasattr(defer, item), msg % item)


    def testAccumulator(self):
        """
        Test the behaviour of deferred_accumulator in various cases.
        """
        dfr1 = defer.succeed(None)
        dfr2 = defer.succeed(None)
        dfr3 = defer.succeed(None)

        tests = [
                ([None, None, None], (True, [])),
                ([None, None, 3   ], (True, [])),
                ([None, None, dfr1], (True, [dfr1])),
                ([None, [],   None], (True, [])),
                ([None, [],   3   ], (True, [])),
                ([None, [],   dfr1], (True, [dfr1])),
                ([None, [dfr1], None], (True, [dfr1])),
                ([None, [dfr1], 3   ], (True, [dfr1])),
                ([None, [dfr1], dfr2], (True, [dfr1, dfr2])),
                ]
        for (args, result) in tests:
            self.assertEquals(defer.deferred_accumulator(*args), result)

