Commit | Line | Data |
---|---|---|
610cfd61 SM |
1 | /* Self tests for the filtered_iterator class. |
2 | ||
b811d2c2 | 3 | Copyright (C) 2019-2020 Free Software Foundation, Inc. |
610cfd61 SM |
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 | ||
26 | namespace selftests { | |
27 | ||
28 | /* An iterator class that iterates on integer arrays. */ | |
29 | ||
30 | struct 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 | ||
93 | private: | |
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 | ||
102 | struct even_numbers_only | |
103 | { | |
104 | bool operator() (int n) | |
105 | { | |
106 | return n % 2 == 0; | |
107 | } | |
108 | }; | |
109 | ||
110 | /* Test typical usage. */ | |
111 | ||
112 | static void | |
113 | test_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 | ||
131 | static void | |
132 | test_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 | ||
158 | void | |
159 | _initialize_filtered_iterator_selftests () | |
160 | { | |
161 | selftests::register_test ("filtered_iterator", | |
162 | selftests::test_filtered_iterator); | |
163 | selftests::register_test ("filtered_iterator_eq", | |
164 | selftests::test_filtered_iterator_eq); | |
165 | } |