def test_remove_raises_ValueError_when_value_not_in_deque(self):
        d = ArrayDeque()
        elements = ['foo', 'bar', 'baz', 'bar']
        d._data[2:6] = elements
        d._size = 4
        d._front = 2

        self.assertRaises(ValueError, d.remove, 'spam')
    def test_add_last_doubles_deque_size_if_capacity_reached(self):
        expected_result = ArrayDeque.DEFAULT_CAPACITY * 2
        d = ArrayDeque()

        for e in range(ArrayDeque.DEFAULT_CAPACITY + 1):
            d.add_last(e)
        result = len(d._data)

        self.assertEqual(result, expected_result)
    def test_setitem_raises_IndexError_with_integer_index_out_of_range(self):
        d = ArrayDeque()
        elements = ['foo', 'bar', 'baz']
        d._data[2:5] = elements
        d._front = 2
        d._size = 3

        self.assertRaises(IndexError, d.__setitem__, 3, 'nope')
        self.assertRaises(IndexError, d.__setitem__, -4, 'nope')
    def test_getitem_raises_NotImplementedError_with_slice_object_parameter(
            self):
        d = ArrayDeque()
        elements = ['foo', 'bar', 'baz', 'spam', 'eggs']
        d._data[2:7] = elements
        d._front = 2
        d._size = 5

        self.assertRaises(NotImplementedError, d.__getitem__, slice(0, 2))
    def test_remove_shifts_elements_from_shorter_end_of_deque(self):
        d = ArrayDeque()
        elements = ['1st', '2nd', '3rd', '4th', '5th', '6th', '7th']
        d._data[0:7] = elements
        d._front = 0
        d._size = 7

        # ['1st', '2nd', '3rd', '4th', '5th', '6th', '7th']
        #    0      1      2      3      4      5      6
        # for i in range self._size -> i in range(7):
        # current = 1
        # 1 < self._size // 2 -> 1 < 3
        #

        d.remove('2nd')

        self.assertEqual(d._data[1:7],
                         ['1st', '3rd', '4th', '5th', '6th', '7th'])
        self.assertEqual(d._front,
                         1)  # front moved as elements left of center shifted

        d.remove('6th')

        self.assertEqual(d._data[1:6], ['1st', '3rd', '4th', '5th', '7th'])
        self.assertEqual(d._front, 1)  # the front has not moved
    def test_getitem_returns_correct_element_with_negative_integer_index(self):
        d = ArrayDeque()
        expected_result = 'foo'
        elements = [expected_result, 'bar', 'baz']
        d._data[2:5] = elements
        d._front = 2
        d._size = 3

        result = d[-3]

        self.assertEqual(result, expected_result)
    def test_setitem_replaces_correct_element_with_positive_integer_index(
            self):
        d = ArrayDeque()
        expected_result = 'spam'
        elements = ['foo', 'bar', 'baz']
        d._data[2:5] = elements
        d._front = 2
        d._size = 3

        d[0] = expected_result
        result = d[0]

        self.assertEqual(result, expected_result)
    def test_len_returns_size_of_deque(self):
        d = ArrayDeque()
        expected_result = 0

        result = len(d)

        self.assertEqual(result, expected_result)

        d._data = ['foo']
        d._size = 1
        expected_result = 1

        result = len(d)

        self.assertEqual(result, expected_result)
    def test_constructor_with_maxlen_less_than_default_capacity_shrinks_size(
            self):
        expected_result = 5

        d = ArrayDeque(maxlen=expected_result)  # less than DEFAULT_CAPACITY
        result = len(d._data)

        self.assertEqual(result, expected_result)
    def test_count_returns_correct_number_of_matches_for_value_in_deque(self):
        d = ArrayDeque()
        elements = ['foo', 'bar', 'baz', 'bar']
        d._data[-2:2] = elements
        d._size = 4
        d._front = 8

        self.assertEqual(2, d.count('bar'))
        self.assertEqual(1, d.count('foo'))
        self.assertEqual(0, d.count('spam'))
    def test_rotate_shifts_deque_to_left_with_negative_steps_integer(self):
        d = ArrayDeque()
        elements = ['foo', 'bar', 'baz']
        expected_elements = ['baz', 'foo', 'bar']
        d._data[0:3] = elements
        d._front = 0
        d._size = 3

        d.rotate(-2)

        self.assertEqual(d._data[2:5], expected_elements)
    def test_is_empty_returns_correct_boolean_value(self):
        d = ArrayDeque()

        self.assertTrue(d.is_empty())

        elements = ['foo', 'bar', 'baz']
        d._data[2:5] = elements
        d._size = 3
        d._front = 2

        self.assertFalse(d.is_empty())
    def test_resize_preserves_order_of_enqueued_elements(self):
        elements = ['foo', 'bar', 'baz']
        expected_sequence = [None] * 20
        expected_sequence[0:3] = elements
        d = ArrayDeque()
        d._data[2:5] = elements
        d._size = 3
        d._front = 2

        d._resize(20)

        self.assertSequenceEqual(d._data, expected_sequence)
    def test_remove_deletes_first_instance_of_value_in_deque(self):
        d = ArrayDeque()
        elements = ['foo', 'bar', 'baz', 'bar']
        d._data[2:6] = elements
        d._size = 4
        d._front = 2

        d.remove('bar')

        self.assertEqual(d._size, 3)
        self.assertIn('bar', d._data)
        self.assertEqual(d._data[3:6], ['foo', 'baz', 'bar'])
    def test_add_last_adds_an_element_to_the_back_of_deque(self):
        elements = ['foo', 'bar']
        expected_result = 'baz'
        d = ArrayDeque()
        d._data[2:4] = elements
        d._size = 2
        d._front = 2

        d.add_last(expected_result)
        result = d._data[4]

        self.assertEqual(result, expected_result)
    def test_clear_resets_deque_resizes_data_to_default_capacity_without_maxlen(
            self):
        d = ArrayDeque()
        elements = ['foo', 'bar', 'baz']
        d._data[2:5] = elements
        d._front = 2
        d._size = 3

        d.clear()

        self.assertEqual(d._size, 0)
        self.assertEqual(d._front, 0)
        self.assertEqual(len(d._data), d.DEFAULT_CAPACITY)
    def test_clear_resets_deque_resizes_data_to_maxlen_with_maxlen_provided(
            self):
        d = ArrayDeque(maxlen=5)
        elements = ['foo', 'bar', 'baz']
        d._data[2:5] = elements
        d._front = 2
        d._size = 3

        d.clear()

        self.assertEqual(d._size, 0)
        self.assertEqual(d._front, 0)
        self.assertEqual(len(d._data), d._maxlen)
    def test_last_returns_last_element_without_removing_it(self):
        elements = ['foo', 'bar', 'baz']
        expected_result = 'baz'
        d = ArrayDeque()
        d._data[2:5] = elements
        d._size = 3
        d._front = 2

        result = d.last()

        self.assertEqual(result, expected_result)
        self.assertIn(expected_result, d._data)
    def test_delete_last_returns_and_removes_last_element_from_deque(self):
        elements = ['foo', 'bar']
        expected_result = 'bar'
        d = ArrayDeque()
        d._data[2:4] = elements
        d._size = 2
        d._front = 2

        result = d.delete_last()

        self.assertEqual(d._size, 1)
        self.assertEqual(result, expected_result)
        self.assertNotIn('bar', d._data)
    def test_delete_last_raises_Empty_exception_if_deque_is_empty(self):
        d = ArrayDeque()

        self.assertRaises(Empty, d.delete_last)
    def test_is_full_returns_correct_boolean_value(self):
        d = ArrayDeque()
        elements = ['foo', 'bar', 'baz', 'spam', 'eggs']
        d._data[2:7] = elements
        d._size = 5
        d._front = 2

        self.assertFalse(d.is_full())

        d = ArrayDeque(maxlen=5)
        elements = ['foo', 'bar', 'baz', 'spam', 'eggs']
        d._data = elements
        d._size = 5

        self.assertTrue(d.is_full())
    def test_resize_increases_capacity(self):
        d = ArrayDeque()

        d._resize(50)

        self.assertEqual(len(d._data), 50)