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