import unittest
import path
import sys
from cStringIO import StringIO

from pynto import util

class TestItem:
    def __init__ (self, value):
        self.value = value
        return

    def __str__ (self):
        return "%d: (%d)" % (id(self), self.value)

    pass

def _debug (string):
    #print string
    return

class TestWorkStar (unittest.TestCase):

    def _executeScript (self, _script, workclass):
        work = workclass (None)

        sidx = 0

        # Go through the script provided and replace all numbers
        # with TestItem objects.
        script = list (_script)
        itemdict = {}
        for idx in range (len (script)):
            if script[idx] > 0:
                sval = script[idx]
                try:
                    script[idx] = itemdict[sval]
                except KeyError:
                    item = TestItem (sval)
                    itemdict[sval] = item
                    script[idx] = item
                    pass
                pass
            pass

        _debug ("Executing Script:")
        for item in script:
            _debug (str (item))
        
        while isinstance (script[sidx], TestItem):
            _debug ("Push %s" % script[sidx])
            work += script[sidx]
            sidx += 1
            pass

        for item in work:
            if script[sidx] < 0:
                _debug ("Pop %s" % item)
                self.assertEqual (item.value,
                                  -script[sidx],
                                  "Failed at index %d: found %d, not %d" %
                                  (sidx, item.value, -script[sidx]))
                sidx += 1
                pass

            if sidx >= len (script): continue

            while isinstance (script[sidx], TestItem):
                _debug ("Push %s" % script[sidx])
                work += script[sidx]
                sidx += 1
                pass
            
            pass

        self.assertEqual (sidx,
                          len (script),
                          "Script not completely consumed")

        return

    def testSimple (self):

        """ Simple push all, pop all pattern across all three types of
        worklists. """
        
        for klass in (util.WorkList, util.WorkSet, util.TransientWorkSet):
            self._executeScript ( (1,2,3,-1,-2,-3), klass )
        return

    def testSimpleInterweave (self):

        """ Simple interwoven push/pop pattern across all three types of
        worklists. """
        
        for klass in (util.WorkList, util.WorkSet, util.TransientWorkSet):
            self._executeScript ( (1,2,-1,3,-2,-3), klass )
        return

    def testDuplicateList (self):

        """ Duplicate pattern across a WorkList """
        
        self._executeScript ( (1,2,-1,-2,2,2,-2,4,-2,-4), util.WorkList )
        return

    def testDuplicateSet (self):

        """ Duplicate pattern across a WorkSet """
        
        self._executeScript ( (1,2,-1,-2,2,2,4,-4), util.WorkSet )
        return

    def testDuplicateTSet (self):

        """ Duplicate pattern across a TransientWorkSet """
        
        self._executeScript ( (1,2,-1,-2,2,2,4,-2,-4), util.TransientWorkSet )
        return

    pass

def add_tests (suite):
    for testname in dir (TestWorkStar):
        if testname.startswith ('test'):
            suite.addTest (TestWorkStar(testname))
            pass
        pass
    return

if __name__ == "__main__":
    unittest.main ()
