emmental/tests/test_store.py

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])