import unittest
import path
import sys, string
from cStringIO import StringIO

from pynto import chelpers

class TestRJBuffer (unittest.TestCase):

    def _run_script (self):

        pass

    def testBoundaries8n (self):

        """ Tests illegal neg offset with set8 """
        
        rjb = chelpers.RJBuffer (10, 1)
        self.failUnlessRaises (ValueError, lambda: rjb.set8 (-1, 1))
        return

    def testBoundaries8p (self):

        """ Tests illegal pos offset with set8 """
        
        rjb = chelpers.RJBuffer (10, 1)
        self.failUnlessRaises (ValueError, lambda: rjb.set8 (10, 1))
        return

    def testBoundaries16 (self):

        """ Tests illegal offsets with set16 """

        # Initial size 10 and big endian
        rjb = chelpers.RJBuffer (10, 1)
        
        self.failUnlessRaises (ValueError, lambda: rjb.set16 (-1, 1))
        self.failUnlessRaises (ValueError, lambda: rjb.set16 (9, 1))
        self.failUnlessRaises (ValueError, lambda: rjb.set16 (10, 1))
        return

    def testBoundaries32 (self):

        """ Tests illegal offsets with set32 """
        
        # Initial size 10 and big endian
        rjb = chelpers.RJBuffer (10, 1)
        
        self.failUnlessRaises (ValueError, lambda: rjb.set32 (-1, 1))
        self.failUnlessRaises (ValueError, lambda: rjb.set32 (7, 1))
        self.failUnlessRaises (ValueError, lambda: rjb.set32 (8, 1))
        self.failUnlessRaises (ValueError, lambda: rjb.set32 (9, 1))
        self.failUnlessRaises (ValueError, lambda: rjb.set32 (10, 1))
        return

    def testSizeSmall (self):

        """ Grows buffer and check size. """
        
        # Initial size 10 and big endian
        rjb = chelpers.RJBuffer (10, 1)
        rjb.grow (5)
        self.assertEquals (5, rjb.size())
        return

    def testSizeLarge (self):

        """ Grows buffer and check size. """
        
        # Initial size 10 and big endian
        rjb = chelpers.RJBuffer (10, 1)
        rjb.grow (10*1024)
        self.assertEquals (10*1024, rjb.size())
        return

    def testStrSmall (self):

        """ Writes data and does a str().  No resizing. """
        
        rjb = chelpers.RJBuffer (20, 1)
        rjb.grow (18)
        for i in range (18): rjb.set8 (i, i)

        expres = "00 01 02 03 04 05 06 07  08 09 0a 0b 0c 0d 0e 0f\n"
        expres+= "10 11 \n"
        
        self.assertEquals (str(rjb), expres)
                           
        return

    def testStrLarge (self):

        """ Writes data and does a str().  One resize. """
        
        rjb = chelpers.RJBuffer (20, 1)
        rjb.grow (18)
        for i in range (18): rjb.set8 (i, i)
        rjb.grow (18)
        for i in range (18): rjb.set8 (i, i)

        expres = "00 01 02 03 04 05 06 07  08 09 0a 0b 0c 0d 0e 0f\n"
        expres+= "10 11 00 01 02 03 04 05  06 07 08 09 0a 0b 0c 0d\n"
        expres+= "0e 0f 10 11 \n"
        
        self.assertEquals (str(rjb), expres)
                           
        return rjb

    def testShrinkwrap (self):

        """ After running testStrLarge(), runs shrinkwrap. """

        rjb = self.testStrLarge ()
        expres = str (rjb)
        rjb.shrinkwrap ()
        self.assertEquals (str(rjb), expres)
        self.assertEquals (rjb.capacity, rjb.size())
        return

    def testPPCDisassemble (self):

        """ Tests canonical PPC disassembly.  Note that this should
        work regardless of whether we are running on a PPC processor. """

        # Some PPC assembly (big endian):
        ppcopcodes = """
        7273005f
        646f5f6d
        6163685f
        6e6f7469
        66795f70
        6f72745f
        64656c65
        74656400
        5f646f5f"""

        # Corresponding disassembly:
        disasm = """
        00000000:  andi.      r19,r19,95
        00000004:  oris       r15,r3,24429
        00000008:  ori        r3,r11,26719
        0000000c:  xoris      r15,r19,29801
        00000010:  oris       r25,r19,24432
        00000014:  xoris      r18,r27,29791
        00000018:  oris       r5,r3,27749
        0000001c:  andis.     r5,r3,25600
        00000020:  rlwnm.     r4,r27,r13,29,15
        """
        
        # strip all whitespace from the above string
        for ws in string.whitespace:
            ppcopcodes = ppcopcodes.replace (ws, '')
            pass

        # Create an rjbuffer
        rjblen = len (ppcopcodes) / 2     # 2 bytes per real byte
        rjb = chelpers.RJBuffer (rjblen, 1)
        rjb.grow (rjblen)

        # now feed it to the RJBuffer; we set it a byte at a time
        offset = 0
        while offset < rjblen:
            intval = int (ppcopcodes[offset*2:offset*2+2], 16)
            rjb.set8 (offset, intval)
            offset += 1
            pass

        # now disassemble! (canonically)
        res = rjb.ppc_disasm (True)
        
        # compare the result line by line
        reslines = res.split ('\n')
        correctlines  = res.split ('\n')

        self.assertEqual (len (reslines), len (correctlines),
                          "Number of lines in output not the same!")
        
        for rl, cl in zip (reslines, correctlines):
            self.assertEqual (rl.strip(), cl.strip())
            pass
        
        pass

    pass

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

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

