Skip to content

Commit

Permalink
Unit tests coverage. PEP8. Setup long description.
Browse files Browse the repository at this point in the history
Change-Id: Ib60f991d6ca1f60f08add1b1e353eaa0fb2724d4
  • Loading branch information
laurentluce committed Dec 1, 2015
1 parent d3c75bb commit bb61316
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 21 deletions.
22 changes: 16 additions & 6 deletions lfucache/lfu_cache.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
class Node(object):
"""Node containing data, pointers to previous and next node."""

def __init__(self, data):
self.data = data
self.prev = None
Expand All @@ -15,10 +16,12 @@ def __init__(self):

def add_node(self, cls, data):
"""Add node instance of class cls."""

return self.insert_node(cls, data, self.tail, None)

def insert_node(self, cls, data, prev, next):
"""Insert node instance of class cls."""

node = cls(data)
node.prev = prev
node.next = next
Expand Down Expand Up @@ -46,6 +49,7 @@ def remove_node(self, node):

def remove_node_by_data(self, data):
"""Remove node which data is equal to data."""

node = self.head
while node:
if node.data == data:
Expand All @@ -55,6 +59,7 @@ def remove_node_by_data(self, data):

def get_nodes_data(self):
"""Return list nodes data as a list."""

data = []
node = self.head
while node:
Expand All @@ -64,8 +69,11 @@ def get_nodes_data(self):


class FreqNode(DoublyLinkedList, Node):
"""Frequency node containing linked list of item nodes with
same frequency."""
"""Frequency node.
Frequency node contains a linked list of item nodes with same frequency.
"""

def __init__(self, data):
DoublyLinkedList.__init__(self)
Node.__init__(self, data)
Expand Down Expand Up @@ -122,7 +130,7 @@ def access(self, key):

if not next_freq_node or next_freq_node.data != freq_node.data + 1:
next_freq_node = self.insert_freq_node(freq_node.data + 1,
freq_node, next_freq_node)
freq_node, next_freq_node)
item_node = next_freq_node.add_item_node(key)
tmp.parent = next_freq_node

Expand Down Expand Up @@ -150,6 +158,7 @@ def get_lfu(self):

def delete_lfu(self):
"""Remove the first item node from the first frequency node.
Remove the LFU item from the dictionary.
"""
if not self.head:
Expand All @@ -162,8 +171,9 @@ def delete_lfu(self):
self.remove_freq_node(freq_node)

def __repr__(self):
"""Display access frequency list and items list using the
representation:
"""Display access frequency list and items.
Using the representation:
freq1: [item, item, ...]
freq2: [item, item]
...
Expand All @@ -179,6 +189,6 @@ def __repr__(self):
class DuplicateException(Exception):
pass


class NotFoundException(Exception):
pass

20 changes: 20 additions & 0 deletions lfucache/test/all_tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
"""Run all of the tests."""
import sys
import unittest2 as unittest


def main(args=None):
unittest_dir = '.'
unittest_suite = unittest.defaultTestLoader.discover(unittest_dir)

kwargs = {}
if args and '-v' in args:
kwargs['verbosity'] = 2
runner = unittest.TextTestRunner(sys.stdout, "Unittests",
**kwargs)
results = runner.run(unittest_suite)
return results.wasSuccessful()

if __name__ == '__main__':
status = main(sys.argv[1:])
sys.exit(int(not status))
2 changes: 2 additions & 0 deletions lfucache/test/coverage.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
coverage run --source=$PYTHONPATH/lfucache --omit=$PYTHONPATH/lfucache/test/* all_tests.py
coverage report --omit=$PYTHONPATH/lfucache/test/* -m
29 changes: 15 additions & 14 deletions lfucache/test/test_lfu_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import lfucache.lfu_cache as lfu_cache


class TestLfuCache(unittest.TestCase):

def setUp(self):
Expand Down Expand Up @@ -30,16 +31,16 @@ def test_add_freq_item_nodes(self):
freq_node1 = self.cache.insert_freq_node(1, None, None)
freq_node2 = self.cache.insert_freq_node(2, freq_node1, None)
freq_node1_item_node1 = freq_node1.insert_item_node('a', None, None)
freq_node1_item_node2 = freq_node1.insert_item_node('b',
freq_node1_item_node1, None)
freq_node1.insert_item_node('b', freq_node1_item_node1, None)
freq_node2_item_node2 = freq_node2.insert_item_node('d', None, None)
freq_node2_item_node1 = freq_node2.insert_item_node('c', None,
freq_node2_item_node1 = freq_node2.insert_item_node(
'c', None,
freq_node2_item_node2)
freq_node2_item_node4 = freq_node2.insert_item_node('f',
freq_node2_item_node2, None)
freq_node2_item_node3 = freq_node2.insert_item_node('e',
freq_node2_item_node2, freq_node2_item_node4)
freq_node2_item_node5 = freq_node2.add_item_node('g')
freq_node2_item_node4 = freq_node2.insert_item_node(
'f', freq_node2_item_node2, None)
freq_node2_item_node3 = freq_node2.insert_item_node(
'e', freq_node2_item_node2, freq_node2_item_node4)
freq_node2.add_item_node('g')

nodes_data = freq_node1.get_nodes_data()
self.assertEqual(nodes_data, ['a', 'b'])
Expand All @@ -65,7 +66,7 @@ def test_insert(self):
self.cache.insert('k3', 'd3')

nodes_data = self.cache.get_nodes_data()
self.assertEqual(nodes_data, [1,])
self.assertEqual(nodes_data, [1, ])

nodes_data = self.cache.head.get_nodes_data()
self.assertEqual(nodes_data, ['k1', 'k2', 'k3'])
Expand All @@ -76,14 +77,14 @@ def test_insert(self):
self.assertEqual(self.cache.items['k2'].data, 'd2')
self.assertEqual(self.cache.items['k2'].parent, self.cache.head)
self.assertEqual(self.cache.items['k2'].node,
self.cache.head.head.next)
self.cache.head.head.next)
self.assertEqual(self.cache.items['k3'].data, 'd3')
self.assertEqual(self.cache.items['k3'].parent, self.cache.head)
self.assertEqual(self.cache.items['k3'].node,
self.cache.head.head.next.next)
self.cache.head.head.next.next)

self.assertRaises(lfu_cache.DuplicateException, self.cache.insert,
'k3', 'd3')
'k3', 'd3')

def test_access(self):
self.cache.insert('k1', 'd1')
Expand Down Expand Up @@ -121,7 +122,7 @@ def test_access(self):

def test_get_lfu(self):
self.assertRaises(lfu_cache.NotFoundException,
self.cache.get_lfu)
self.cache.get_lfu)

self.cache.insert('k1', 'd1')
self.cache.insert('k2', 'd2')
Expand All @@ -139,7 +140,7 @@ def test_get_lfu(self):

def test_delete_lfu(self):
self.assertRaises(lfu_cache.NotFoundException,
self.cache.delete_lfu)
self.cache.delete_lfu)

self.cache.insert('k1', 'd1')
self.cache.insert('k2', 'd2')
Expand Down
2 changes: 2 additions & 0 deletions pep8.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
flake8 lfucache
exit
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@
version='0.1',
packages=['lfucache',],
license='MIT',
long_description=open('README.md').read(),
long_description='Cache with LFU eviction scheme implemented in Python with complexity O(1) for insertion, access and deletion.',
)

0 comments on commit bb61316

Please sign in to comment.