# Copyright 2022 (c) Anna Schumaker """Tests our idle queues.""" import unittest import unittest.mock import emmental.db.idle from gi.repository import GObject from gi.repository import GLib @unittest.mock.patch("gi.repository.GLib.source_remove") @unittest.mock.patch("gi.repository.GLib.idle_add", return_value=42) class TestIdleQueue(unittest.TestCase): """Test the base Idle Queue.""" def setUp(self): """Set up common variables.""" self.queue = emmental.db.idle.Queue() def test_init(self, mock_idle_add: unittest.mock.Mock, mock_source_removed: unittest.mock.Mock): """Test that the Idle Queue is initialized properly.""" self.assertIsInstance(self.queue, GObject.GObject) self.assertEqual(self.queue.total, 0) self.assertEqual(self.queue.progress, 0.0) self.assertFalse(self.queue.running) self.assertTrue(self.queue.enabled) self.assertListEqual(self.queue._tasks, []) self.assertIsNone(self.queue._idle_id) def test_getitem(self, mock_idle_add: unittest.mock.Mock, mock_source_removed: unittest.mock.Mock): """Test the __getitem__() function.""" self.queue._tasks = [1, 2, 3] self.assertEqual(self.queue[0], 1) self.assertEqual(self.queue[1], 2) self.assertEqual(self.queue[2], 3) self.assertIsNone(self.queue[3]) def test_cancel(self, mock_idle_add: unittest.mock.Mock, mock_source_removed: unittest.mock.Mock): """Test canceling queued tasks.""" self.queue.push(1) self.queue.progress = 0.42 self.queue.cancel() mock_source_removed.assert_called_with(42) self.assertListEqual(self.queue._tasks, []) self.assertIsNone(self.queue._idle_id) self.assertEqual(self.queue.total, 0) self.assertEqual(self.queue.progress, 0.0) def test_complete(self, mock_idle_add: unittest.mock.Mock, mock_source_removed: unittest.mock.Mock): """Test completing queued tasks.""" func = unittest.mock.Mock(return_value=True) self.queue.push(func, 1) self.queue.push(func, 2) self.queue.complete() func.assert_has_calls([unittest.mock.call(1), unittest.mock.call(2)]) self.assertFalse(self.queue.running) self.assertListEqual(self.queue._tasks, []) mock_source_removed.assert_called_with(42) func.reset_mock() self.queue.complete() func.assert_not_called() def test_push_enabled(self, mock_idle_add: unittest.mock.Mock, mock_source_removed: unittest.mock.Mock): """Test adding an idle task to an enabled idle queue.""" func = unittest.mock.Mock(return_value=True) self.assertIsNone(self.queue.push(func, 1)) mock_idle_add.assert_called_with(self.queue.run_task) func.assert_not_called() self.assertListEqual(self.queue._tasks, [(func, 1)]) self.assertEqual(self.queue.total, 1) self.assertEqual(self.queue._idle_id, 42) self.assertTrue(self.queue.running) mock_idle_add.reset_mock() self.assertIsNone(self.queue.push(func, 2)) self.assertListEqual(self.queue._tasks, [(func, 1), (func, 2)]) self.assertEqual(self.queue.total, 2) mock_idle_add.assert_not_called() def test_push_disabled(self, mock_idle_add: unittest.mock.Mock, mock_source_removed: unittest.mock.Mock): """Test adding an idle task to a disabled idle queue.""" self.queue.enabled = False func = unittest.mock.Mock(return_value=True) self.assertTrue(self.queue.push(func, 1)) self.assertListEqual(self.queue._tasks, []) self.assertEqual(self.queue.total, 0) self.assertFalse(self.queue.running) self.assertIsNone(self.queue._idle_id) mock_idle_add.assert_not_called() func.assert_called_with(1) func = unittest.mock.Mock(return_value=False) self.assertFalse(self.queue.push(func, 2)) mock_idle_add.assert_not_called() func.assert_called_with(2) def test_push_now(self, mock_idle_add: unittest.mock.Mock, mock_source_removed: unittest.mock.Mock): """Test pushing an idle task with now=True.""" func = unittest.mock.Mock(return_value=True) self.assertTrue(self.queue.push(func, 1, now=True)) self.assertListEqual(self.queue._tasks, []) self.assertEqual(self.queue.total, 0) self.assertFalse(self.queue.running) self.assertIsNone(self.queue._idle_id) mock_idle_add.assert_not_called() func.assert_called_with(1) def test_push_many_enabled(self, mock_idle_add: unittest.mock.Mock, mock_source_removed: unittest.mock.Mock): """Test adding several calls to one function at one time.""" func = unittest.mock.Mock(return_value=True) self.queue.push_many(func, [(1,), (2,), (3,)]) self.assertListEqual(self.queue._tasks, [(func, 1), (func, 2), (func, 3)]) self.assertEqual(self.queue.total, 3) self.assertEqual(self.queue._idle_id, 42) self.assertTrue(self.queue.running) mock_idle_add.assert_called_with(self.queue.run_task) func.assert_not_called() def test_push_many_disabled(self, mock_idle_add: unittest.mock.Mock, mock_source_removed: unittest.mock.Mock): """Test push_many() with the idle queue disabled.""" self.queue.enabled = False func = unittest.mock.Mock(return_value=True) self.queue.push_many(func, [(1,), (2,), (3,)]) func.assert_has_calls([unittest.mock.call(1), unittest.mock.call(2), unittest.mock.call(3)]) mock_idle_add.assert_not_called() def test_push_many_now(self, mock_idle_add: unittest.mock.Mock, mock_source_removed: unittest.mock.Mock): """Test push_many() with now=True.""" func = unittest.mock.Mock(return_value=True) self.queue.push_many(func, [(1,), (2,), (3,)], now=True) func.assert_has_calls([unittest.mock.call(1), unittest.mock.call(2), unittest.mock.call(3)]) mock_idle_add.assert_not_called() def test_run_task(self, mock_idle_add: unittest.mock.Mock, mock_source_removed: unittest.mock.Mock): """Test manually running idle tasks.""" func = unittest.mock.Mock(return_value=True) self.queue.push_many(func, [(i,) for i in range(5)]) self.assertEqual(self.queue.total, 5) for i in range(5): expected = GLib.SOURCE_REMOVE if i == 4 else GLib.SOURCE_CONTINUE with self.subTest(i=i, expected=expected): self.assertEqual(self.queue.run_task(), expected) func.assert_called_with(i) self.assertAlmostEqual(self.queue.progress, 0 if i == 4 else (i + 1) / 5) self.assertEqual(self.queue.running, i != 4) self.assertIsNone(self.queue._idle_id) self.queue.run_task() def test_rerun_task(self, mock_idle_add: unittest.mock.Mock, mock_source_removed: unittest.mock.Mock): """Test rerunning a task.""" func = unittest.mock.Mock(return_value=False) self.queue.push(func, 1) self.queue.push(func, 2) self.queue.run_task() self.assertListEqual(self.queue._tasks, [(func, 1), (func, 2)])