/* Self tests for the filtered_iterator class. Copyright (C) 2019-2020 Free Software Foundation, Inc. This file is part of GDB. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "gdbsupport/common-defs.h" #include "gdbsupport/selftest.h" #include "gdbsupport/filtered-iterator.h" #include namespace selftests { /* An iterator class that iterates on integer arrays. */ struct int_array_iterator { using value_type = int; using reference = int &; using pointer = int *; using iterator_category = std::forward_iterator_tag; using difference_type = int; /* Create an iterator that points at the first element of an integer array at ARRAY of size SIZE. */ int_array_iterator (int *array, size_t size) : m_array (array), m_size (size) {} /* Create a past-the-end iterator. */ int_array_iterator () : m_array (nullptr), m_size (0) {} bool operator== (const int_array_iterator &other) const { /* If both are past-the-end, they are equal. */ if (m_array == nullptr && other.m_array == nullptr) return true; /* If just one of them is past-the-end, they are not equal. */ if (m_array == nullptr || other.m_array == nullptr) return false; /* If they are both not past-the-end, make sure they iterate on the same array (we shouldn't compare iterators that iterate on different things). */ gdb_assert (m_array == other.m_array); /* They are equal if they have the same current index. */ return m_cur_idx == other.m_cur_idx; } bool operator!= (const int_array_iterator &other) const { return !(*this == other); } void operator++ () { /* Make sure nothing tries to increment a past the end iterator. */ gdb_assert (m_cur_idx < m_size); m_cur_idx++; /* Mark the iterator as "past-the-end" if we have reached the end. */ if (m_cur_idx == m_size) m_array = nullptr; } int operator* () const { /* Make sure nothing tries to dereference a past the end iterator. */ gdb_assert (m_cur_idx < m_size); return m_array[m_cur_idx]; } private: /* A nullptr value in M_ARRAY indicates a past-the-end iterator. */ int *m_array; size_t m_size; size_t m_cur_idx = 0; }; /* Filter to only keep the even numbers. */ struct even_numbers_only { bool operator() (int n) { return n % 2 == 0; } }; /* Test typical usage. */ static void test_filtered_iterator () { int array[] = { 4, 4, 5, 6, 7, 8, 9 }; std::vector even_ints; const std::vector expected_even_ints { 4, 4, 6, 8 }; filtered_iterator iter (array, ARRAY_SIZE (array)); filtered_iterator end; for (; iter != end; ++iter) even_ints.push_back (*iter); gdb_assert (even_ints == expected_even_ints); } /* Test operator== and operator!=. */ static void test_filtered_iterator_eq () { int array[] = { 4, 4, 5, 6, 7, 8, 9 }; filtered_iterator iter1(array, ARRAY_SIZE (array)); filtered_iterator iter2(array, ARRAY_SIZE (array)); /* They start equal. */ gdb_assert (iter1 == iter2); gdb_assert (!(iter1 != iter2)); /* Advance 1, now they aren't equal (despite pointing to equal values). */ ++iter1; gdb_assert (!(iter1 == iter2)); gdb_assert (iter1 != iter2); /* Advance 2, now they are equal again. */ ++iter2; gdb_assert (iter1 == iter2); gdb_assert (!(iter1 != iter2)); } } /* namespace selftests */ void _initialize_filtered_iterator_selftests (); void _initialize_filtered_iterator_selftests () { selftests::register_test ("filtered_iterator", selftests::test_filtered_iterator); selftests::register_test ("filtered_iterator_eq", selftests::test_filtered_iterator_eq); }