예제 #1
0
    def __init__(self, name):
        """
        Initializes the C{TestLibDll} class.

          1. Call the constructor of the base class.
          2. Create an aggreget of the C{DLinklist} class.
          3. Define an object to be used for a C{ctypes} C{POINTER} object.

        @param name: The name used by the C{TestCase} class.
        @raise LibraryNotFoundException: If the C{C} library cannot be found.
        """
        super(TestLibDll, self).__init__(name)
        self._dll = DLinklist(disableLogging=True)
        self._list_p = None
예제 #2
0
class TestLibDll(unittest.TestCase):
    """
    This class runs testunit test on all the function in my C{C} linklist
    library.
    """

    def __init__(self, name):
        """
        Initializes the C{TestLibDll} class.

          1. Call the constructor of the base class.
          2. Create an aggreget of the C{DLinklist} class.
          3. Define an object to be used for a C{ctypes} C{POINTER} object.

        @param name: The name used by the C{TestCase} class.
        @raise LibraryNotFoundException: If the C{C} library cannot be found.
        """
        super(TestLibDll, self).__init__(name)
        self._dll = DLinklist(disableLogging=True)
        self._list_p = None

    def setUp(self):
        """
        Initialize the list for each unit test.

        @return: C{None}
        """
        # Create and initialize list
        self._list_p = self._initList(sizeof(Info))
        #print "Address of list_p: %s" % hex(cast(self._list_p, c_void_p).value)

    def tearDown(self):
        """
        Destroy entire list.

        @return: C{None}
        """
        # Destroy list.
        self._destroyList()

    def test_InfoType(self):
        """
        Check that the C{Info} class is the correct type.

        @return: C{None}
        """
        msg = "Invalid Info type is not a subclass of ctypes Structure."

        try:
            self._dll.checkInfoType(Info())
        except:
            self.fail(msg)

        class BadInfo(object):
            pass

        try:
            self._dll.checkInfoType(BadInfo())
            self.fail(msg)
        except APIException:
            pass

    def test_sizeofList(self):
        """
        Test that the C{Python} C{List} object is the same size as the C{C}
        C{List} structure.

        @return: C{None}
        """
        pSizeof = sizeof(List)
        cSizeof = self._dll._lib._getListSize()
        msg = "Python sizeof(List): %s, C sizeof(List): %s" % (pSizeof, cSizeof)
        self.assertTrue(pSizeof == cSizeof, msg=msg)

    def test_DDL_Version(self):
        """
        Test that a string is returned.

        The C{C} function doc string::

          Ver: 1.3.0  Dec 24 2011
          -------------------------------
          Developed by: Carl J. Nobile
          Contributions: Charlie Buckheit
                         Graham Inchley
                         Wai-Sun Chia
                         Mark M. Feenstra
                         Lianqi Qiu

        @return: C{None}
        """
        devBy = " Developed by: Carl J. Nobile"
        version = string_at(self._dll.version())

        try:
            self.assertIn(devBy, version)  # Python version => 2.7
        except:
            self.assertTrue(devBy in version)

    def test_DLL_IsListEmpty(self):
        """
        Check that the list is empty.

        @return: C{None}
        """
        self._isListEmpty(test=True)

    def test_DLL_IsListFull(self):
        """
        Check that the list is not full.

        @return: C{None}
        """
        self._isListFull(test=False)

    def test_DLL_GetNumberOfRecords(self):
        """
        Check that the correct number of records are returned.

        @return: C{None}
        """
        # Test that list is empty
        self._getNumberOfRecords(test=0)
        # Test list with one record
        value = "This is a test."
        self._addRecord(Info(value))
        self._getNumberOfRecords(test=1)

    def test_DLL_SetSearchModes(self):
        """
        Check that the correct return codes are returned when setting the
        search modes.

        @return: C{None}
        """
        # Test the defaults
        self._setSearchModes(SrchOrigin.ORIGIN_DEFAULT,
                             SrchDir.DIRECTION_DEFAULT)
        # Test invalid SrchOrigin type
        self._setSearchModes(10, SrchDir.DIRECTION_DEFAULT,
                             result=Return.NOT_MODIFIED)
        # Test invalid SrchDir type
        self._setSearchModes(SrchOrigin.ORIGIN_DEFAULT, 10,
                             result=Return.NOT_MODIFIED)

    def test_DLL_GetSearchModes(self):
        """
        Check that the set search modes are returned.

        @return: C{None}
        """
        # Test the defaults
        self._getSearchModes()
        # Test SrchOrigin.TAIL and SrchDir.UP
        self._setSearchModes(SrchOrigin.TAIL, SrchDir.UP)
        self._getSearchModes(test=(SrchOrigin.TAIL, SrchDir.UP))

    def test_DLL_GetCurrentIndex(self):
        """
        Check that the current index is returned.

        @return: C{None}
        """
        # Test no records
        self._getCurrentIndex()
        # Test one record
        value = "This is a test."
        self._addRecord(Info(value))
        self._getCurrentIndex(test=1)

    def test_DLL_CurrentPointerToHead(self):
        """
        Check that the current pointer gets moved to the head of the list
        properly and that the correct return codes are returned.

        @return: C{None}
        """
        # Test no records
        self._currentPointerToHead(result=Return.NULL_LIST)
        # Test with two records
        value = "This is test record one."
        self._addRecord(Info(value))
        value = "This is test record two."
        self._addRecord(Info(value))
        self._getCurrentIndex(test=2)
        self._currentPointerToHead()
        self._getCurrentIndex(test=1)

    def test_DLL_CurrentPointerToTail(self):
        """
        Check that the current pointer gets moved to the tail of the list
        properly and that the correct return codes are returned.

        @return: C{None}
        """
        # Test no records
        self._currentPointerToTail(result=Return.NULL_LIST)
        # Test with two records
        value = "This is test record one."
        self._addRecord(Info(value))
        value = "This is test record two."
        self._addRecord(Info(value))
        self._currentPointerToHead()
        self._getCurrentIndex(test=1)
        self._currentPointerToTail()
        self._getCurrentIndex(test=2)

    def test_DLL_IncrementCurrentPointer(self):
        """
        Check that the current pointer gets incremented properly and that the
        correct return codes are returned.

        @return: C{None}
        """
        # Test no records
        self._incrementCurrentPointer(result=Return.NULL_LIST)
        # Test with two records
        value = "This is test record one."
        self._addRecord(Info(value))
        value = "This is test record two."
        self._addRecord(Info(value))
        self._currentPointerToHead()
        self._incrementCurrentPointer()
        self._getCurrentIndex(test=2)
        # Test past end
        self._incrementCurrentPointer(result=Return.NOT_FOUND)

    def test_DLL_DecrementCurrentPointer(self):
        """
        Check that the current pointer gets decremented properly and that the
        correct return codes are returned.

        @return: C{None}
        """
        # Test no records
        self._decrementCurrentPointer(result=Return.NULL_LIST)
        # Test with two records
        value = "This is test record one."
        self._addRecord(Info(value))
        value = "This is test record two."
        self._addRecord(Info(value))
        self._decrementCurrentPointer()
        self._getCurrentIndex(test=1)
        # Test past beginning
        self._decrementCurrentPointer(result=Return.NOT_FOUND)

    def test_DLL_Store_RestoreCurrentPointer(self):
        """
        Check that the store and restore of the current pointer is properly
        done and the correct return codes are returned.

        @return: C{None}
        """
        # Test no records
        self._storeCurrentPointer(result=Return.NOT_FOUND)
        self._restoreCurrentPointer(result=Return.NOT_FOUND)
        # Test with two records
        value = "This is test record one."
        self._addRecord(Info(value))
        value = "This is test record two."
        self._addRecord(Info(value))
        self._storeCurrentPointer()
        self._decrementCurrentPointer()
        self._getCurrentIndex(test=1)
        self._restoreCurrentPointer()
        self._getCurrentIndex(test=2)

    def test_DLL_AddRecord(self):
        """
        Check that records are added to the link list properly, the index
        values are correct after each add, and the correct return codes are
        returned.

        @return: C{None}
        """
        # Test non-sorted addRecord.
        value = "This is a test."
        self._addRecord(Info(value))
        self._getCurrentIndex(test=1)
        self._getNumberOfRecords(test=1)
        self._deleteEntireList()
        self._getCurrentIndex(test=0)
        self._getNumberOfRecords(test=0)
        # Test with three records
        values = []
        values.append("ZZZZ - This is test record one.")
        values.append("AAAA - This is test record two.")
        values.append("NNNN - This is test record three.")

        for value in values:
            self._addRecord(Info(value), self._dll.compare())

        # This next test will fail in version 1.2.1 and below.
        self._getCurrentIndex(test=2)
        values.sort()
        #print values
        self._currentPointerToHead()
        self._getCurrentIndex(test=1)
        size = len(values)

        for idx in range(size):
            self._getCurrentRecord(Info(), test=values[idx])
            idx < (size-1) and self._incrementCurrentPointer()

        self.assertTrue(idx == (size-1))

    def test_DLL_InsertRecord(self):
        """
        Check that inserted records are added properly based on C{InsertDir},
        the index values are correct after each insert, and the correct return
        codes are returned.

        @return: C{None}
        """
        values = []
        values.append("ZZZZ - This is test record one.")
        values.append("AAAA - This is test record two.")
        values.append("NNNN - This is test record three.")
        record = Info(values[0])
        self._insertRecord(record, InsertDir.ABOVE)
        self._getNumberOfRecords(test=1)
        record = Info(values[1])
        self._insertRecord(record, InsertDir.ABOVE)
        self._getNumberOfRecords(test=2)
        record = Info(values[2])
        self._insertRecord(record, InsertDir.BELOW)
        self._getNumberOfRecords(test=3)
        self._currentPointerToHead()
        record = Info()
        values.sort()
        size = len(values)

        for idx in range(size):
            self._getCurrentRecord(record, test=values[idx])
            #print record.value
            idx < (size-1) and self._incrementCurrentPointer()

        self.assertTrue(idx == (size-1))

    def test_DLL_SwapRecord(self):
        """
        Check that the current record is swapped correctly based on
        C{InsertDir}, the index values are correct after each swap, and the
        correct return codes are returned.

        @return: C{None}
        """
        # Test no records
        self._swapRecord(InsertDir.ABOVE, result=Return.NULL_LIST)
        # Test invalid direction
        values = []
        values.append("ZZZZ - This is test record one.")
        values.append("AAAA - This is test record two.")
        values.append("NNNN - This is test record three.")

        for value in values:
            self._addRecord(Info(value))

        self._swapRecord(10, result=Return.NOT_MODIFIED)
        self._getNumberOfRecords(test=3)
        # Test no record after tail
        self._getCurrentIndex(test=3)
        self._swapRecord(InsertDir.BELOW, result=Return.NOT_FOUND)
        # Test that the three records are in the correct order.
        self._getCurrentIndex(test=3)
        self._decrementCurrentPointer()
        self._swapRecord(InsertDir.ABOVE)
        self._getCurrentIndex(test=1)
        self._incrementCurrentPointer()
        self._swapRecord(InsertDir.BELOW)
        # Test no record before head
        self._currentPointerToHead()
        self._swapRecord(InsertDir.ABOVE, result=Return.NOT_FOUND)
        # Continue with correct order test.
        record = Info()
        values.sort()
        size = len(values)

        for idx in range(size):
            self._getCurrentRecord(record, test=values[idx])
            #print record.value
            idx < (size-1) and self._incrementCurrentPointer()

        self.assertTrue(idx == (size-1))

    def test_DLL_UpdateCurrentRecord(self):
        """
        Check that a record gets updated correctly, the index values are
        correct after each update, and the correct return codes are returned.

        @return: C{None}
        """
        # Test no records
        value = "This is a text."
        self._updateCurrentRecord(Info(value),
                                  result=Return.NULL_LIST)
        self._getCurrentIndex(test=0)
        # Test that the record got updated
        self._addRecord(Info(value))
        self._getCurrentRecord(Info(), test=value)
        self._getCurrentIndex(test=1)
        value = "This is another text."
        self._updateCurrentRecord(Info(value))
        self._getCurrentIndex(test=1)
        self._getCurrentRecord(Info(), test=value)
        self._getCurrentIndex(test=1)

    def test_DLL_DeleteCurrentRecord(self):
        """
        Check that a record gets deleted correctly, the index values are
        correct after each update, and the correct return codes are returned.

        @return: C{None}
        """
        # Test no records
        self._deleteCurrentRecord(result=Return.NULL_LIST)
        self._getCurrentIndex(test=0)
        # Test that the record got deleted
        value = "This is a text."
        self._addRecord(Info(value))
        self._getCurrentIndex(test=1)
        self._deleteCurrentRecord()
        self._isListEmpty(test=True)

    def test_DLL_DeleteEntireList(self):
        """
        Check that the entire list is deleted properly, the index values are
        correct after the delete, and the correct return codes are returned.

        @return: C{None}
        """
        # Test no records
        self._deleteEntireList(result=Return.NULL_LIST)
        # Test thst the list gets deleted
        values = []
        values.append("ZZZZ - This is test record one.")
        values.append("AAAA - This is test record two.")
        values.append("NNNN - This is test record three.")

        for value in values:
            self._addRecord(Info(value))

        self._getNumberOfRecords(test=3)
        self._deleteEntireList()
        self._isListEmpty(test=True)

    def test_DLL_FindRecord(self):
        """
        Check that records are found correctly, the index values are correct
        after each query, and the correct return codes are returned.

        @return: C{None}
        """
        # Test for null function pointer
        self._findRecord(Info(), Info(), None,
                         result=Return.NULL_FUNCTION)
        # Test no records
        self._findRecord(Info(), Info(), self._dll.compare(),
                         result=Return.NULL_LIST)
        # Test that record if found
        values = []
        values.append("ZZZZ - This is test record one.")
        values.append("AAAA - This is test record two.")
        values.append("NNNN - This is test record three.")

        for value in values:
            self._addRecord(Info(value))

        self._getNumberOfRecords(test=3)
        record = Info()
        self._findRecord(record, Info(values[1]), self._dll.compare())
        # Test record not found
        self._findRecord(record, Info("Record not found."),
                         self._dll.compare(), result=Return.NOT_FOUND)

    def test_DLL_FindNthRecord(self):
        """
        Check that records are found correctly based on the skip value, the
        index values are correct after each query, and the correct return
        codes are returned.

        @return: C{None}
        """
        # Test no records
        self._findNthRecord(Info(), 1, result=Return.NULL_LIST)
        # Test for the Nth record, step = 1 then 5
        # (Uses defaults in the list struct, SrchOrigin.HEAD and SrchDir.DOWN)
        values = []
        values.append("ZZZZ - This is test record one.")
        values.append("AAAA - This is test record two.")
        values.append("NNNN - This is test record three.")
        values.append("YYYY - This is test record four.")
        values.append("BBBB - This is test record five.")
        values.append("MMMM - This is test record six.")

        for value in values:
            self._addRecord(Info(value))

        self._getNumberOfRecords(test=6)
        self._getCurrentIndex(test=6)
        self._findNthRecord(Info(), 1, test=values[1])
        self._getCurrentIndex(test=2)
        self._findNthRecord(Info(), 5, test=values[5])
        self._getCurrentIndex(test=6)
        # Test invalid skip value with SrchOrigin.HEAD and SrchDir.DOWN
        self._findNthRecord(Info(), 0, test=values[1],
                            result=Return.NOT_FOUND)
        self._findNthRecord(Info(), 6, test=values[1],
                            result=Return.NOT_FOUND)
        # Test change search mode to SrchOrigin.TAIL and SrchDir.UP
        self._setSearchModes(SrchOrigin.TAIL, SrchDir.UP)
        self._findNthRecord(Info(), 1, test=values[4])
        self._getCurrentIndex(test=5)
        self._findNthRecord(Info(), 5, test=values[0])
        self._getCurrentIndex(test=1)
        # Test invalid skip value with SrchOrigin.TAIL and SrchDir.UP
        self._findNthRecord(Info(), 6, test=values[5],
                            result=Return.NOT_FOUND)
        # Test change search mode to SrchOrigin.CURRENT and SrchDir.DOWN
        self._setSearchModes(SrchOrigin.CURRENT, SrchDir.DOWN)
        # TODO -- enhance the increment and decrement current pointer to
        # to increment or decrement a number of records.
        self._incrementCurrentPointer()
        self._incrementCurrentPointer()
        self._findNthRecord(Info(), 1, test=values[3])
        self._getCurrentIndex(test=4)
        # Test invalid skip value with SrchOrigin.CURRENT and SrchDir.DOWN
        self._findNthRecord(Info(), 3, test=values[5],
                            result=Return.NOT_FOUND)
        self._getCurrentIndex(test=4)
        # Test change search mode to SrchOrigin.CURRENT and SrchDir.UP
        self._setSearchModes(SrchOrigin.CURRENT, SrchDir.UP)
        self._findNthRecord(Info(), 1, test=values[2])
        self._getCurrentIndex(test=3)
        # Test invalid skip value with SrchOrigin.CURRENT and SrchDir.UP
        self._findNthRecord(Info(), 3, test=values[0],
                            result=Return.NOT_FOUND)
        self._getCurrentIndex(test=3)

    def test_DLL_GetCurrentRecord(self):
        """
        Check that the current record is returned correctly, the index values
        are correct after the get, and the correct return codes are returned.

        @return: C{None}
        """
        # Test no records
        self._getCurrentRecord(Info(), result=Return.NULL_LIST)
        self._getCurrentIndex(test=0)
        # Test for curent record
        value = "This is test record."
        self._addRecord(Info(value))
        self._getCurrentRecord(Info(), test=value)
        self._getCurrentIndex(test=1)

    def test_DLL_GetPriorRecord(self):
        """
        Check that the prior record is returned correctly, the index values
        are correct after the get, and the correct return codes are returned.

        @return: C{None}
        """
        # Test no records
        self._getPriorRecord(Info(), result=Return.NULL_LIST)
        # Test for curent record
        values = []
        values.append("ZZZZ - This is test record one.")
        values.append("AAAA - This is test record two.")

        for value in values:
            self._addRecord(Info(value))

        self._currentPointerToTail()
        self._getPriorRecord(Info(), test=values[0])
        self._getCurrentIndex(test=1)

    def test_DLL_GetNextRecord(self):
        """
        Check that the next record is returned correctly, the index values are
        correct after the get, and the correct return codes are returned.

        @return: C{None}
        """
        # Test no records
        self._getNextRecord(Info(), result=Return.NULL_LIST)
        # Test for curent record
        values = []
        values.append("ZZZZ - This is test record one.")
        values.append("AAAA - This is test record two.")

        for value in values:
            self._addRecord(Info(value))

        self._currentPointerToHead()
        self._getNextRecord(Info(), test=values[1])
        self._getCurrentIndex(test=2)

    def test_DLL_Save_LoadList(self):
        """
        Check that the list is saved and loaded correctly, the index values are
        correct after the loads, the sorting on load is done properly, and the
        correct return codes are returned.

        @return: C{None}
        """
        filePath = "/tmp/unittest.data"
        # Test no records
        self._saveList(filePath, result=Return.NULL_LIST)
        # Test saving list to dick
        values = []
        values.append("ZZZZ - This is test record one.")
        values.append("AAAA - This is test record two.")
        values.append("NNNN - This is test record three.")
        values.append("YYYY - This is test record four.")
        values.append("BBBB - This is test record five.")
        values.append("MMMM - This is test record six.")

        for value in values:
            self._addRecord(Info(value))

        self._getNumberOfRecords(test=6)
        self._saveList(filePath)
        # Test already has data in list.
        self._saveList(filePath, result=Return.NOT_MODIFIED)
        # Test load list.
        self._loadList(filePath, self._dll.compare())
        # The current index is an arbitrary number depending on the sort
        # algorithm used. This next test will fail in version 1.2.1 and below.
        self._getCurrentIndex(test=3)
        self._currentPointerToHead()
        self._getCurrentIndex(test=1)
        # Test open error.
        self._loadList("", self._dll.compare(), result=Return.OPEN_ERROR)
        self._getCurrentIndex(test=1)
        os.remove(filePath)

    #
    # Methods to interface into ctypes.
    #
    def _initList(self, infoSize):
        """
        Prepare the link list for use and asserts that there are no
        C{APIException} or C{FunctionException} exceptions, and the C{list_p}
        object is valid.

        @param infoSize: The size in bytes of the user defined C{Info} class.
        @type infoSize: C{int}
        @return: A pinter to the link list.
        @rtype: C{ctypes POINTER}
        """
        try:
            list_p = self._dll.create(infoSize)
        except APIException, e:
            self.fail(e)
        except FunctionException, e:
            self.fail(e)