1/* Self tests for the filtered_iterator class. 2 3 Copyright (C) 2019-2020 Free Software Foundation, Inc. 4 5 This file is part of GDB. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19 20#include "gdbsupport/common-defs.h" 21#include "gdbsupport/selftest.h" 22#include "gdbsupport/filtered-iterator.h" 23 24#include <iterator> 25 26namespace selftests { 27 28/* An iterator class that iterates on integer arrays. */ 29 30struct int_array_iterator 31{ 32 using value_type = int; 33 using reference = int &; 34 using pointer = int *; 35 using iterator_category = std::forward_iterator_tag; 36 using difference_type = int; 37 38 /* Create an iterator that points at the first element of an integer 39 array at ARRAY of size SIZE. */ 40 int_array_iterator (int *array, size_t size) 41 : m_array (array), m_size (size) 42 {} 43 44 /* Create a past-the-end iterator. */ 45 int_array_iterator () 46 : m_array (nullptr), m_size (0) 47 {} 48 49 bool operator== (const int_array_iterator &other) const 50 { 51 /* If both are past-the-end, they are equal. */ 52 if (m_array == nullptr && other.m_array == nullptr) 53 return true; 54 55 /* If just one of them is past-the-end, they are not equal. */ 56 if (m_array == nullptr || other.m_array == nullptr) 57 return false; 58 59 /* If they are both not past-the-end, make sure they iterate on the 60 same array (we shouldn't compare iterators that iterate on different 61 things). */ 62 gdb_assert (m_array == other.m_array); 63 64 /* They are equal if they have the same current index. */ 65 return m_cur_idx == other.m_cur_idx; 66 } 67 68 bool operator!= (const int_array_iterator &other) const 69 { 70 return !(*this == other); 71 } 72 73 void operator++ () 74 { 75 /* Make sure nothing tries to increment a past the end iterator. */ 76 gdb_assert (m_cur_idx < m_size); 77 78 m_cur_idx++; 79 80 /* Mark the iterator as "past-the-end" if we have reached the end. */ 81 if (m_cur_idx == m_size) 82 m_array = nullptr; 83 } 84 85 int operator* () const 86 { 87 /* Make sure nothing tries to dereference a past the end iterator. */ 88 gdb_assert (m_cur_idx < m_size); 89 90 return m_array[m_cur_idx]; 91 } 92 93private: 94 /* A nullptr value in M_ARRAY indicates a past-the-end iterator. */ 95 int *m_array; 96 size_t m_size; 97 size_t m_cur_idx = 0; 98}; 99 100/* Filter to only keep the even numbers. */ 101 102struct even_numbers_only 103{ 104 bool operator() (int n) 105 { 106 return n % 2 == 0; 107 } 108}; 109 110/* Test typical usage. */ 111 112static void 113test_filtered_iterator () 114{ 115 int array[] = { 4, 4, 5, 6, 7, 8, 9 }; 116 std::vector<int> even_ints; 117 const std::vector<int> expected_even_ints { 4, 4, 6, 8 }; 118 119 filtered_iterator<int_array_iterator, even_numbers_only> 120 iter (array, ARRAY_SIZE (array)); 121 filtered_iterator<int_array_iterator, even_numbers_only> end; 122 123 for (; iter != end; ++iter) 124 even_ints.push_back (*iter); 125 126 gdb_assert (even_ints == expected_even_ints); 127} 128 129/* Test operator== and operator!=. */ 130 131static void 132test_filtered_iterator_eq () 133{ 134 int array[] = { 4, 4, 5, 6, 7, 8, 9 }; 135 136 filtered_iterator<int_array_iterator, even_numbers_only> 137 iter1(array, ARRAY_SIZE (array)); 138 filtered_iterator<int_array_iterator, even_numbers_only> 139 iter2(array, ARRAY_SIZE (array)); 140 141 /* They start equal. */ 142 gdb_assert (iter1 == iter2); 143 gdb_assert (!(iter1 != iter2)); 144 145 /* Advance 1, now they aren't equal (despite pointing to equal values). */ 146 ++iter1; 147 gdb_assert (!(iter1 == iter2)); 148 gdb_assert (iter1 != iter2); 149 150 /* Advance 2, now they are equal again. */ 151 ++iter2; 152 gdb_assert (iter1 == iter2); 153 gdb_assert (!(iter1 != iter2)); 154} 155 156} /* namespace selftests */ 157 158void _initialize_filtered_iterator_selftests (); 159void 160_initialize_filtered_iterator_selftests () 161{ 162 selftests::register_test ("filtered_iterator", 163 selftests::test_filtered_iterator); 164 selftests::register_test ("filtered_iterator_eq", 165 selftests::test_filtered_iterator_eq); 166} 167