Anna Schumaker
61fc252172
This ListStore implementation uses a key function to keep the items sorted at all times. Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
259 lines
10 KiB
Python
259 lines
10 KiB
Python
# Copyright 2023 (c) Anna Schumaker.
|
|
"""Tests our custom Python-based ListStore."""
|
|
import unittest
|
|
import emmental.store
|
|
from gi.repository import GObject
|
|
from gi.repository import Gio
|
|
|
|
|
|
class Object(GObject.GObject):
|
|
"""A simple object for testing."""
|
|
|
|
value = GObject.Property(type=int)
|
|
|
|
|
|
class TestListStore(unittest.TestCase):
|
|
"""Test case for the Python-based ListStore."""
|
|
|
|
def items_changed(self, store: emmental.store.ListStore,
|
|
pos: int, removed: int, added: int) -> None:
|
|
"""Handle the items-changed signal."""
|
|
self.changed = (pos, removed, added)
|
|
|
|
def setUp(self):
|
|
"""Set up common variables."""
|
|
self.store = emmental.store.ListStore()
|
|
self.store.connect("items-changed", self.items_changed)
|
|
self.changed = (None, None, None)
|
|
|
|
def test_init(self):
|
|
"""Check that the ListStore is initialized properly."""
|
|
self.assertIsInstance(self.store, GObject.GObject)
|
|
self.assertIsInstance(self.store, Gio.ListModel)
|
|
self.assertListEqual(self.store.items, [])
|
|
self.assertEqual(self.store.n_items, 0)
|
|
|
|
def test_get_item_type(self):
|
|
"""Test getting the item type for the ListStore."""
|
|
self.assertEqual(self.store.get_item_type(), GObject.GObject.__gtype__)
|
|
|
|
def test_get_item(self):
|
|
"""Test accessing items in the ListStore."""
|
|
objs = [Object(value=i) for i in range(5)]
|
|
self.store.extend(objs)
|
|
|
|
for i, obj in enumerate(objs):
|
|
with self.subTest(i=i):
|
|
self.assertEqual(self.store.get_item(i), obj)
|
|
self.assertEqual(self.store[i], obj)
|
|
|
|
self.assertIsNone(self.store.get_item(6))
|
|
|
|
def test_append(self):
|
|
"""Test the ListStore's append() function."""
|
|
for i in [0, 1, 2]:
|
|
with self.subTest(i=i):
|
|
self.assertTrue(self.store.append(Object(value=i)))
|
|
self.assertTupleEqual(self.changed, (i, 0, 1))
|
|
self.assertListEqual([obj.value for obj in self.store.items],
|
|
[v for v in range(i + 1)])
|
|
|
|
def test_clear(self):
|
|
"""Test clearing a ListStore."""
|
|
self.store.clear()
|
|
self.assertTupleEqual(self.changed, (None, None, None))
|
|
|
|
self.store.extend([Object(value=i) for i in range(5)])
|
|
self.store.clear()
|
|
self.assertTupleEqual(self.changed, (0, 5, 0))
|
|
|
|
def test_extend(self):
|
|
"""Test appending multiple values to the ListStore."""
|
|
self.store.extend([])
|
|
self.assertTupleEqual(self.changed, (None, None, None))
|
|
self.assertListEqual(self.store.items, [])
|
|
|
|
self.store.extend([Object(value=0), Object(value=1)])
|
|
self.assertTupleEqual(self.changed, (0, 0, 2))
|
|
self.assertListEqual([obj.value for obj in self.store.items],
|
|
[0, 1])
|
|
|
|
self.store.extend([Object(value=2), Object(value=3), Object(value=4)])
|
|
self.assertTupleEqual(self.changed, (2, 0, 3))
|
|
self.assertListEqual([obj.value for obj in self.store.items],
|
|
[0, 1, 2, 3, 4])
|
|
|
|
def test_index(self):
|
|
"""Test finding the index of items in the ListStore."""
|
|
objs = [Object(value=i) for i in range(5)]
|
|
self.store.extend(objs)
|
|
|
|
for i, obj in enumerate(objs):
|
|
with self.subTest(i=i):
|
|
self.assertEqual(self.store.index(obj), i)
|
|
self.assertTrue(obj in self.store)
|
|
|
|
self.assertIsNone(self.store.index(Object(value=10)))
|
|
self.assertFalse(Object(value=10) in self.store)
|
|
|
|
def test_insert(self):
|
|
"""Test the ListStore's insert() function."""
|
|
self.assertTrue(self.store.insert(0, Object(value=0)))
|
|
self.assertTupleEqual(self.changed, (0, 0, 1))
|
|
self.assertListEqual([obj.value for obj in self.store.items],
|
|
[0])
|
|
|
|
self.assertTrue(self.store.insert(0, Object(value=1)))
|
|
self.assertTupleEqual(self.changed, (0, 0, 1))
|
|
self.assertListEqual([obj.value for obj in self.store.items],
|
|
[1, 0])
|
|
|
|
self.assertTrue(self.store.insert(5, Object(value=5)))
|
|
self.assertTupleEqual(self.changed, (2, 0, 1))
|
|
self.assertListEqual([obj.value for obj in self.store.items],
|
|
[1, 0, 5])
|
|
|
|
self.assertTrue(self.store.insert(-3, Object(value=3)))
|
|
self.assertTupleEqual(self.changed, (0, 0, 1))
|
|
self.assertListEqual([obj.value for obj in self.store.items],
|
|
[3, 1, 0, 5])
|
|
|
|
def test_length(self):
|
|
"""Test requesting the ListStore's length."""
|
|
for n in [0, 1, 2]:
|
|
with self.subTest(n=n):
|
|
self.assertEqual(self.store.get_n_items(), n)
|
|
self.assertEqual(self.store.n_items, n)
|
|
self.assertEqual(len(self.store), n)
|
|
|
|
self.store.append(Object(value=n))
|
|
|
|
def test_pop(self):
|
|
"""Test popping objects from the ListStore."""
|
|
self.assertIsNone(self.store.pop(0))
|
|
self.assertTupleEqual(self.changed, (None, None, None))
|
|
|
|
objs = [Object(value=v) for v in range(3)]
|
|
self.store.extend(objs)
|
|
self.changed = (None, None, None)
|
|
|
|
self.assertIsNone(self.store.pop(5))
|
|
self.assertTupleEqual(self.changed, (None, None, None))
|
|
|
|
self.assertEqual(self.store.pop(0), objs[0])
|
|
self.assertTupleEqual(self.changed, (0, 1, 0))
|
|
self.assertListEqual([obj.value for obj in self.store.items],
|
|
[1, 2])
|
|
|
|
def test_remove(self):
|
|
"""Test removing objects from the ListStore."""
|
|
objs = [Object(value=v) for v in range(3)]
|
|
self.store.extend(objs)
|
|
|
|
self.assertTrue(self.store.remove(objs[0]))
|
|
self.assertEqual(self.changed, (0, 1, 0))
|
|
|
|
self.changed = (None, None, None)
|
|
self.assertFalse(self.store.remove(objs[0]))
|
|
self.assertTupleEqual(self.changed, (None, None, None))
|
|
|
|
|
|
class TestSortedList(unittest.TestCase):
|
|
"""Test case for our SortedList implementation."""
|
|
|
|
def items_changed(self, store: emmental.store.SortedList,
|
|
pos: int, removed: int, added: int) -> None:
|
|
"""Handle the items-changed signal."""
|
|
self.changed = (pos, removed, added)
|
|
|
|
def key_func(self, obj: Object) -> int:
|
|
"""Get a sort key for Objects."""
|
|
return obj.value
|
|
|
|
def setUp(self):
|
|
"""Set up common variables."""
|
|
self.store = emmental.store.SortedList(self.key_func)
|
|
self.store.connect("items-changed", self.items_changed)
|
|
self.changed = (None, None, None)
|
|
|
|
def test_init(self):
|
|
"""Check that the SortedList is initialized properly."""
|
|
self.assertIsInstance(self.store, emmental.store.ListStore)
|
|
self.assertEqual(self.store.key_func, self.key_func)
|
|
|
|
def test_append(self):
|
|
"""Test the SortedList's append() function."""
|
|
self.assertTrue(self.store.append(Object(value=2)))
|
|
self.assertTupleEqual(self.changed, (0, 0, 1))
|
|
self.assertListEqual([obj.value for obj in self.store.items],
|
|
[2])
|
|
|
|
self.assertTrue(self.store.append(Object(value=0)))
|
|
self.assertTupleEqual(self.changed, (0, 0, 1))
|
|
self.assertListEqual([obj.value for obj in self.store.items],
|
|
[0, 2])
|
|
|
|
self.assertTrue(self.store.append(Object(value=1)))
|
|
self.assertTupleEqual(self.changed, (1, 0, 1))
|
|
self.assertListEqual([obj.value for obj in self.store.items],
|
|
[0, 1, 2])
|
|
|
|
self.changed = (None, None, None)
|
|
for value in [0, 1, 2]:
|
|
with self.subTest(value=value):
|
|
self.assertFalse(self.store.append(Object(value=value)))
|
|
self.assertTupleEqual(self.changed, (None, None, None))
|
|
self.assertListEqual([obj.value for obj in self.store.items],
|
|
[0, 1, 2])
|
|
|
|
def test_extend(self):
|
|
"""Test adding multiple values to the SortedList."""
|
|
self.store.extend([])
|
|
self.assertTupleEqual(self.changed, (None, None, None))
|
|
self.assertListEqual(self.store.items, [])
|
|
|
|
self.store.extend([Object(value=1), Object(value=3)])
|
|
self.assertTupleEqual(self.changed, (0, 0, 2))
|
|
self.assertListEqual([obj.value for obj in self.store.items],
|
|
[1, 3])
|
|
|
|
self.store.extend([Object(value=0), Object(value=2), Object(value=4)])
|
|
self.assertTupleEqual(self.changed, (0, 2, 5))
|
|
self.assertListEqual([obj.value for obj in self.store.items],
|
|
[0, 1, 2, 3, 4])
|
|
|
|
def test_index(self):
|
|
"""Test finding the index of items in the SortedList."""
|
|
objs = [Object(value=i) for i in range(5)]
|
|
self.store.extend(objs)
|
|
|
|
for i, obj in enumerate(objs):
|
|
with self.subTest(i=i):
|
|
self.assertEqual(self.store.index(obj), i)
|
|
self.assertIsNone(self.store.index(Object(value=10)))
|
|
|
|
def test_insert(self):
|
|
"""Test the SortedList's insert() function."""
|
|
self.assertTrue(self.store.insert(2, Object(value=2)))
|
|
self.assertTupleEqual(self.changed, (0, 0, 1))
|
|
self.assertListEqual([obj.value for obj in self.store.items],
|
|
[2])
|
|
|
|
self.assertTrue(self.store.insert(1, Object(value=0)))
|
|
self.assertTupleEqual(self.changed, (0, 0, 1))
|
|
self.assertListEqual([obj.value for obj in self.store.items],
|
|
[0, 2])
|
|
|
|
self.assertTrue(self.store.insert(0, Object(value=1)))
|
|
self.assertTupleEqual(self.changed, (1, 0, 1))
|
|
self.assertListEqual([obj.value for obj in self.store.items],
|
|
[0, 1, 2])
|
|
|
|
self.changed = (None, None, None)
|
|
for i, obj in enumerate(self.store):
|
|
with self.subTest(i=i):
|
|
self.assertFalse(self.store.insert(0, obj))
|
|
self.assertTupleEqual(self.changed, (None, None, None))
|
|
self.assertListEqual([obj.value for obj in self.store.items],
|
|
[0, 1, 2])
|