From 17b544f8bca0fcc1068e312d0497f84276e1c322 Mon Sep 17 00:00:00 2001 From: Michael Bradley Date: Thu, 9 Jan 2025 00:00:04 +1300 Subject: [PATCH] Add tests for other future queues --- pyority_queue.pyi | 16 +++-- tests/indexed_queue.py | 130 +++++++++++++++++++++++++++++++++++++++++ tests/keyed_queue.py | 95 ++++++++++++++++++++++++++++++ tests/pure_queue.py | 34 ++++++++++- 4 files changed, 269 insertions(+), 6 deletions(-) create mode 100644 tests/indexed_queue.py create mode 100644 tests/keyed_queue.py diff --git a/pyority_queue.pyi b/pyority_queue.pyi index e76f406..f31ebb9 100644 --- a/pyority_queue.pyi +++ b/pyority_queue.pyi @@ -25,6 +25,11 @@ class Queue[Data](ABC): :return: The next item in the queue """ + def pop(self) -> Data: + """ + :return: The next item in the queue + """ + class PureQueue[Data: Comparable](Queue[Data]): """ @@ -36,11 +41,6 @@ class PureQueue[Data: Comparable](Queue[Data]): :param items: An optional list of priorities with which to initialize the queue """ - def pop(self) -> Data: - """ - :return: The next item in the queue - """ - def insert(self, item: Data) -> None: """ :param item: Item to insert into the queue @@ -87,3 +87,9 @@ class IndexedQueue[Data: Hashable, Priority: Comparable](Queue[Data]): """ :param key: The item to delete from the queue """ + + def __contains__(self, key: Data) -> bool: + """ + :param key: The item to check the existence of + :return: Whether the item is in the queue + """ diff --git a/tests/indexed_queue.py b/tests/indexed_queue.py new file mode 100644 index 0000000..4d0d347 --- /dev/null +++ b/tests/indexed_queue.py @@ -0,0 +1,130 @@ +from typing import Any + +import pytest + +from pyority_queue import Comparable, IndexedQueue + + +type IndexedQueueInitializer = dict[Any, Comparable] | list[tuple[Any, Comparable]] | tuple[tuple[Any, Comparable], ...] + + +def test_empty_creation(): + queue = IndexedQueue() + assert len(queue) == 0 + + +@pytest.mark.parametrize("items", ( + [], + [("a", 0), ("b", 1), ("c", 2)], + ((0, 0), (1, 1), (2, 2)), + ((0.0, 0.0), (1.0, 1.0), (2.0, 2.0)), + ((lambda: None, 0)), + ((Exception(), 0.0)), + (([], -1)), + {}, + {"a": 0, "b": 1, "c": 2}, +)) +def test_creation(items: IndexedQueueInitializer): + queue = IndexedQueue() + assert len(queue) == len(items) + + +@pytest.mark.parametrize("items", ( + [], + ((0, 0),), + ((-1, -1), (3, 3)), +)) +def test_iteration(items: IndexedQueueInitializer): + queue = IndexedQueue(items) + assert len(list(queue)) == len(items) + + +@pytest.mark.parametrize("items", ( + [], + (("a", -3), ("b", 5)), + (("c", 3.0), ("b", 2.0), ("a", 1.0)), + (("c", 3), ("f", 6), ("h", 8), ("e", 5), ("g", 7), ("d", 4), ("b", 2), ("a", 0)), +)) +def test_sorting(items: IndexedQueueInitializer): + queue = IndexedQueue(items) + in_order = list(queue) + assert in_order == sorted(in_order) + + +def test_insertion(): + queue = IndexedQueue({"a": 1, "b": 2, "c": 3}) + queue["d"] = 4 + queue["e"] = 5 + assert list(queue) == ["a", "b", "c", "d", "e"] + + +def test_removal(): + queue = IndexedQueue({"a": 1, "b": 2, "c": 3}) + assert queue.pop() == "a" + assert queue.pop() == "b" + assert queue.pop() == "c" + assert len(queue) == 0 + + +def test_mixed_removal(): + queue = IndexedQueue({"a": 1, "b": 2, "c": 3}) + assert queue.pop() == "a" + assert list(queue) == ["b", "c"] + + +def test_empty_removal(): + queue = IndexedQueue() + with pytest.raises(IndexError): + queue.pop() + + +def test_duplicates(): + queue = IndexedQueue[str, int]((("a", 0), ("a", 0), ("a", 2))) + queue["b"] = 1 + queue["b"] = 3 + assert list(queue) == ["a", "b"] + + +def test_deletion(): + queue = IndexedQueue({"a": 1, "b": 2, "c": 3}) + del queue["a"] + del queue["b"] + assert list(queue) == ["c"] + + +def test_empty_deletion(): + queue = IndexedQueue() + with pytest.raises(KeyError): + del queue["a"] + + +def test_in(): + queue = IndexedQueue({"a": 1, "b": 2, "c": 3}) + assert "a" in queue + assert "b" in queue + assert "c" in queue + assert "d" not in queue + del queue["b"] + assert "b" not in queue + + +def test_mixed_iteration(): + queue = IndexedQueue({"a": 1, "b": 2, "c": 3}) + results = [] + for char in queue: + results.append(char) + if len(queue): + queue[queue.pop()] = 10 + assert results == ["a", "c", "b"] + + +def test_iteration_deletion(): + queue = IndexedQueue({"a": 1, "b": 2, "c": 3}) + results = [] + for char in queue: + results.append(char) + if "b" in queue: + del queue["b"] + assert results == ["a", "c"] + + diff --git a/tests/keyed_queue.py b/tests/keyed_queue.py new file mode 100644 index 0000000..811eb6a --- /dev/null +++ b/tests/keyed_queue.py @@ -0,0 +1,95 @@ +from typing import Any + +import pytest + +from pyority_queue import Comparable, KeyedQueue + + +type KeyedQueueInitializer = dict[Any, Comparable] | list[tuple[Any, Comparable]] | tuple[tuple[Any, Comparable], ...] + + +def test_empty_creation(): + queue = KeyedQueue() + assert len(queue) == 0 + + +@pytest.mark.parametrize("items", ( + [], + [("a", 0), ("b", 1), ("c", 2)], + ((0, 0), (1, 1), (2, 2)), + ((0.0, 0.0), (1.0, 1.0), (2.0, 2.0)), + ((lambda: None, 0)), + ((Exception(), 0.0)), + (([], -1)), + {}, + {"a": 0, "b": 1, "c": 2}, +)) +def test_creation(items: KeyedQueueInitializer): + queue = KeyedQueue() + assert len(queue) == len(items) + + +@pytest.mark.parametrize("items", ( + [], + ((0, 0),), + ((-1, -1), (3, 3)), +)) +def test_iteration(items: KeyedQueueInitializer): + queue = KeyedQueue(items) + assert len(list(queue)) == len(items) + + +@pytest.mark.parametrize("items", ( + [], + (("a", -3), ("b", 5)), + (("c", 3.0), ("b", 2.0), ("a", 1.0)), + (("c", 3), ("f", 6), ("h", 8), ("e", 5), ("g", 7), ("d", 4), ("b", 2), ("a", 0)), +)) +def test_sorting(items: KeyedQueueInitializer): + queue = KeyedQueue(items) + in_order = list(queue) + assert in_order == sorted(in_order) + + +def test_insertion(): + queue = KeyedQueue({"a": 1, "b": 2, "c": 3}) + queue["d"] = 4 + queue["e"] = 5 + assert list(queue) == ["a", "b", "c", "d", "e"] + + +def test_removal(): + queue = KeyedQueue[str, int]({"a": 1, "b": 2, "c": 3}) + assert queue.pop() == "a" + assert queue.pop() == "b" + assert queue.pop() == "c" + assert len(queue) == 0 + + +def test_mixed_removal(): + queue = KeyedQueue[str, int]({"a": 1, "b": 2, "c": 3}) + assert queue.pop() == "a" + assert list(queue) == ["b", "c"] + + +def test_empty_removal(): + queue = KeyedQueue() + with pytest.raises(IndexError): + queue.pop() + + +def test_duplicates(): + queue = KeyedQueue[str, int]((("a", 0), ("a", 0), ("a", 2))) + queue["b"] = 1 + queue["b"] = 3 + assert list(queue) == ["a", "a", "b", "a", "b"] + + +def test_mixed_iteration(): + queue = KeyedQueue[str, int]({"a": 1, "b": 2, "c": 3}) + results = [] + for char in queue: + results.append(char) + if len(queue): + queue[queue.pop()] = 10 + assert results == ["a", "c", "b"] diff --git a/tests/pure_queue.py b/tests/pure_queue.py index ce32069..31b1dba 100644 --- a/tests/pure_queue.py +++ b/tests/pure_queue.py @@ -3,7 +3,7 @@ import pytest from pyority_queue import PureQueue -type PureQueueInitializer = list[int | float] | tuple[int | float, ...] +type PureQueueInitializer = list[float] | list[int] | tuple[float, ...] | tuple[int, ...] def test_empty_creation(): @@ -16,6 +16,7 @@ def test_creation(items: PureQueueInitializer): queue = PureQueue() assert len(queue) == len(items) + @pytest.mark.parametrize("items", ([], (0,), (-1, 3), range(100))) def test_iteration(items: PureQueueInitializer): queue = PureQueue(items) @@ -36,8 +37,39 @@ def test_insertion(): assert list(queue) == [0, 2, 3, 4, 6, 7, 8] +def test_removal(): + queue = PureQueue[int]((4, 2, 8, 6)) + assert queue.pop() == 2 + assert queue.pop() == 4 + assert queue.pop() == 6 + assert queue.pop() == 8 + assert len(queue) == 0 + + +def test_mixed_removal(): + queue = PureQueue[int]((4, 2, 8, 6)) + assert queue.pop() == 2 + assert list(queue) == [4, 6, 8] + + +def test_empty_removal(): + queue = PureQueue() + with pytest.raises(IndexError): + queue.pop() + + def test_duplicates(): queue = PureQueue[int]((0, 0, 0, 5, 5)) queue.insert(3) queue.insert(3) assert list(queue) == [0, 0, 0, 3, 3, 5, 5] + + +def test_mixed_iteration(): + queue = PureQueue[int]((4, 2, 8, 6)) + results = [] + for number in queue: + results.append(number) + if len(queue): + queue.insert(queue.pop() * 2) + assert results == [2, 6, 8, 16]