Skip to content

Commit 8bbcc6d

Browse files
authored
[libc++] Add test coverage for unordered containers comparison (#66692)
This patch is a melting pot of changes picked up from https://llvm.org/D61878. It adds a few tests checking corner cases of unordered containers comparison and adds benchmarks for a few unordered_set operations.
1 parent e46de4e commit 8bbcc6d

File tree

4 files changed

+110
-2
lines changed

4 files changed

+110
-2
lines changed

libcxx/benchmarks/ContainerBenchmarks.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,37 @@ static void BM_Rehash(benchmark::State& st, Container c, GenInputs gen) {
179179
}
180180
}
181181

182+
template <class Container, class GenInputs>
183+
static void BM_Compare_same_container(benchmark::State& st, Container, GenInputs gen) {
184+
auto in = gen(st.range(0));
185+
Container c1(in.begin(), in.end());
186+
Container c2 = c1;
187+
188+
benchmark::DoNotOptimize(&(*c1.begin()));
189+
benchmark::DoNotOptimize(&(*c2.begin()));
190+
while (st.KeepRunning()) {
191+
bool res = c1 == c2;
192+
benchmark::DoNotOptimize(&res);
193+
benchmark::ClobberMemory();
194+
}
195+
}
196+
197+
template <class Container, class GenInputs>
198+
static void BM_Compare_different_containers(benchmark::State& st, Container, GenInputs gen) {
199+
auto in1 = gen(st.range(0));
200+
auto in2 = gen(st.range(0));
201+
Container c1(in1.begin(), in1.end());
202+
Container c2(in2.begin(), in2.end());
203+
204+
benchmark::DoNotOptimize(&(*c1.begin()));
205+
benchmark::DoNotOptimize(&(*c2.begin()));
206+
while (st.KeepRunning()) {
207+
bool res = c1 == c2;
208+
benchmark::DoNotOptimize(&res);
209+
benchmark::ClobberMemory();
210+
}
211+
}
212+
182213
} // end namespace ContainerBenchmarks
183214

184215
#endif // BENCHMARK_CONTAINER_BENCHMARKS_H

libcxx/benchmarks/unordered_set_operations.bench.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,25 @@ BENCHMARK_CAPTURE(BM_Rehash,
290290
BENCHMARK_CAPTURE(BM_Rehash, unordered_set_int_arg, std::unordered_set<int>{}, getRandomIntegerInputs<int>)
291291
->Arg(TestNumInputs);
292292

293+
//----------------------------------------------------------------------------//
294+
// BM_Compare
295+
// ---------------------------------------------------------------------------//
296+
297+
BENCHMARK_CAPTURE(
298+
BM_Compare_same_container, unordered_set_string, std::unordered_set<std::string>{}, getRandomStringInputs)
299+
->Arg(TestNumInputs);
300+
301+
BENCHMARK_CAPTURE(BM_Compare_same_container, unordered_set_int, std::unordered_set<int>{}, getRandomIntegerInputs<int>)
302+
->Arg(TestNumInputs);
303+
304+
BENCHMARK_CAPTURE(
305+
BM_Compare_different_containers, unordered_set_string, std::unordered_set<std::string>{}, getRandomStringInputs)
306+
->Arg(TestNumInputs);
307+
308+
BENCHMARK_CAPTURE(
309+
BM_Compare_different_containers, unordered_set_int, std::unordered_set<int>{}, getRandomIntegerInputs<int>)
310+
->Arg(TestNumInputs);
311+
293312
///////////////////////////////////////////////////////////////////////////////
294313
BENCHMARK_CAPTURE(BM_InsertDuplicate, unordered_set_int, std::unordered_set<int>{}, getRandomIntegerInputs<int>)
295314
->Arg(TestNumInputs);

libcxx/test/std/containers/unord/unord.multimap/eq.pass.cpp

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,5 +221,30 @@ int main(int, char**)
221221
}
222222
#endif
223223

224-
return 0;
224+
// Make sure we take into account the number of times that a key repeats into equality.
225+
{
226+
typedef std::pair<int, char> P;
227+
P a[] = {P(1, 'a'), P(1, 'b'), P(1, 'd'), P(2, 'b')};
228+
P b[] = {P(1, 'a'), P(1, 'b'), P(1, 'b'), P(1, 'd'), P(2, 'b')};
229+
230+
std::unordered_multimap<int, char> c1(std::begin(a), std::end(a));
231+
std::unordered_multimap<int, char> c2(std::begin(b), std::end(b));
232+
assert(testEquality(c1, c2, false));
233+
}
234+
235+
// Make sure we incorporate the values into the equality of the maps.
236+
// If we were to compare only the keys (including how many time each key repeats),
237+
// the following test would fail cause only the values differ.
238+
{
239+
typedef std::pair<int, char> P;
240+
P a[] = {P(1, 'a'), P(1, 'b'), P(1, 'd'), P(2, 'b')};
241+
P b[] = {P(1, 'a'), P(1, 'b'), P(1, 'E'), P(2, 'b')};
242+
// ^ different here
243+
244+
std::unordered_multimap<int, char> c1(std::begin(a), std::end(a));
245+
std::unordered_multimap<int, char> c2(std::begin(b), std::end(b));
246+
assert(testEquality(c1, c2, false));
247+
}
248+
249+
return 0;
225250
}

libcxx/test/std/containers/unord/unord.multiset/eq.pass.cpp

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,13 @@
2020

2121
#include <unordered_set>
2222
#include <cassert>
23+
#include <cstddef>
2324

2425
#include "test_macros.h"
2526
#include "min_allocator.h"
2627

28+
#include "test_comparisons.h"
29+
2730
int main(int, char**)
2831
{
2932
{
@@ -178,5 +181,35 @@ int main(int, char**)
178181
}
179182
#endif
180183

181-
return 0;
184+
// Make sure we take into account the number of times that a key repeats into equality.
185+
{
186+
int a[] = {1, 1, 1, 2};
187+
int b[] = {1, 1, 1, 1, 2};
188+
189+
std::unordered_multiset<int> c1(std::begin(a), std::end(a));
190+
std::unordered_multiset<int> c2(std::begin(b), std::end(b));
191+
assert(testEquality(c1, c2, false));
192+
}
193+
194+
// Make sure we behave properly when a custom key predicate is provided.
195+
{
196+
int a[] = {1, 3};
197+
int b[] = {1, 1};
198+
// A very poor hash
199+
struct HashModuloOddness {
200+
std::size_t operator()(int x) const { return std::hash<int>()(x % 2); }
201+
};
202+
// A very poor hash
203+
struct CompareModuloOddness {
204+
bool operator()(int x, int y) const { return (x % 2) == (y % 2); }
205+
};
206+
207+
using Set = std::unordered_multiset<int, HashModuloOddness, CompareModuloOddness>;
208+
Set c1(std::begin(a), std::end(a));
209+
Set c2(std::begin(b), std::end(b));
210+
211+
assert(testEquality(c1, c2, false));
212+
}
213+
214+
return 0;
182215
}

0 commit comments

Comments
 (0)