[libcxx-commits] [libcxx] [libc++] Add test coverage for unordered containers comparison (PR #66692)
Louis Dionne via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Sep 19 08:57:25 PDT 2023
https://github.com/ldionne updated https://github.com/llvm/llvm-project/pull/66692
>From d0b99a2a7c23d7f04583ec6fcf4238b729edbb7f Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Mon, 18 Sep 2023 15:48:39 -0400
Subject: [PATCH] [libc++] Add test coverage for unordered containers
comparison
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.
---
libcxx/benchmarks/ContainerBenchmarks.h | 31 ++++++++++++++++
.../unordered_set_operations.bench.cpp | 19 ++++++++++
.../unord/unord.multimap/eq.pass.cpp | 27 +++++++++++++-
.../unord/unord.multiset/eq.pass.cpp | 35 ++++++++++++++++++-
4 files changed, 110 insertions(+), 2 deletions(-)
diff --git a/libcxx/benchmarks/ContainerBenchmarks.h b/libcxx/benchmarks/ContainerBenchmarks.h
index 5ab6f619b85a8d0..071e46c2a1c6546 100644
--- a/libcxx/benchmarks/ContainerBenchmarks.h
+++ b/libcxx/benchmarks/ContainerBenchmarks.h
@@ -179,6 +179,37 @@ static void BM_Rehash(benchmark::State& st, Container c, GenInputs gen) {
}
}
+template <class Container, class GenInputs>
+static void BM_Compare_same_container(benchmark::State& st, Container, GenInputs gen) {
+ auto in = gen(st.range(0));
+ Container c1(in.begin(), in.end());
+ Container c2 = c1;
+
+ benchmark::DoNotOptimize(&(*c1.begin()));
+ benchmark::DoNotOptimize(&(*c2.begin()));
+ while (st.KeepRunning()) {
+ bool res = c1 == c2;
+ benchmark::DoNotOptimize(&res);
+ benchmark::ClobberMemory();
+ }
+}
+
+template <class Container, class GenInputs>
+static void BM_Compare_different_containers(benchmark::State& st, Container, GenInputs gen) {
+ auto in1 = gen(st.range(0));
+ auto in2 = gen(st.range(0));
+ Container c1(in1.begin(), in1.end());
+ Container c2(in2.begin(), in2.end());
+
+ benchmark::DoNotOptimize(&(*c1.begin()));
+ benchmark::DoNotOptimize(&(*c2.begin()));
+ while (st.KeepRunning()) {
+ bool res = c1 == c2;
+ benchmark::DoNotOptimize(&res);
+ benchmark::ClobberMemory();
+ }
+}
+
} // end namespace ContainerBenchmarks
#endif // BENCHMARK_CONTAINER_BENCHMARKS_H
diff --git a/libcxx/benchmarks/unordered_set_operations.bench.cpp b/libcxx/benchmarks/unordered_set_operations.bench.cpp
index 96aa2e0dfea3be0..d49de576ec9778d 100644
--- a/libcxx/benchmarks/unordered_set_operations.bench.cpp
+++ b/libcxx/benchmarks/unordered_set_operations.bench.cpp
@@ -290,6 +290,25 @@ BENCHMARK_CAPTURE(BM_Rehash,
BENCHMARK_CAPTURE(BM_Rehash, unordered_set_int_arg, std::unordered_set<int>{}, getRandomIntegerInputs<int>)
->Arg(TestNumInputs);
+//----------------------------------------------------------------------------//
+// BM_Compare
+// ---------------------------------------------------------------------------//
+
+BENCHMARK_CAPTURE(
+ BM_Compare_same_container, unordered_set_string, std::unordered_set<std::string>{}, getRandomStringInputs)
+ ->Arg(TestNumInputs);
+
+BENCHMARK_CAPTURE(BM_Compare_same_container, unordered_set_int, std::unordered_set<int>{}, getRandomIntegerInputs<int>)
+ ->Arg(TestNumInputs);
+
+BENCHMARK_CAPTURE(
+ BM_Compare_different_containers, unordered_set_string, std::unordered_set<std::string>{}, getRandomStringInputs)
+ ->Arg(TestNumInputs);
+
+BENCHMARK_CAPTURE(
+ BM_Compare_different_containers, unordered_set_int, std::unordered_set<int>{}, getRandomIntegerInputs<int>)
+ ->Arg(TestNumInputs);
+
///////////////////////////////////////////////////////////////////////////////
BENCHMARK_CAPTURE(BM_InsertDuplicate, unordered_set_int, std::unordered_set<int>{}, getRandomIntegerInputs<int>)
->Arg(TestNumInputs);
diff --git a/libcxx/test/std/containers/unord/unord.multimap/eq.pass.cpp b/libcxx/test/std/containers/unord/unord.multimap/eq.pass.cpp
index d0e578e190c0a18..083fff13b3812fb 100644
--- a/libcxx/test/std/containers/unord/unord.multimap/eq.pass.cpp
+++ b/libcxx/test/std/containers/unord/unord.multimap/eq.pass.cpp
@@ -221,5 +221,30 @@ int main(int, char**)
}
#endif
- return 0;
+ // Make sure we take into account the number of times that a key repeats into equality.
+ {
+ typedef std::pair<int, char> P;
+ P a[] = {P(1, 'a'), P(1, 'b'), P(1, 'd'), P(2, 'b')};
+ P b[] = {P(1, 'a'), P(1, 'b'), P(1, 'b'), P(1, 'd'), P(2, 'b')};
+
+ std::unordered_multimap<int, char> c1(std::begin(a), std::end(a));
+ std::unordered_multimap<int, char> c2(std::begin(b), std::end(b));
+ assert(testEquality(c1, c2, false));
+ }
+
+ // Make sure we incorporate the values into the equality of the maps.
+ // If we were to compare only the keys (including how many time each key repeats),
+ // the following test would fail cause only the values differ.
+ {
+ typedef std::pair<int, char> P;
+ P a[] = {P(1, 'a'), P(1, 'b'), P(1, 'd'), P(2, 'b')};
+ P b[] = {P(1, 'a'), P(1, 'b'), P(1, 'E'), P(2, 'b')};
+ // ^ different here
+
+ std::unordered_multimap<int, char> c1(std::begin(a), std::end(a));
+ std::unordered_multimap<int, char> c2(std::begin(b), std::end(b));
+ assert(testEquality(c1, c2, false));
+ }
+
+ return 0;
}
diff --git a/libcxx/test/std/containers/unord/unord.multiset/eq.pass.cpp b/libcxx/test/std/containers/unord/unord.multiset/eq.pass.cpp
index 22d3207d0ff74a0..7c4cfd63c7bb613 100644
--- a/libcxx/test/std/containers/unord/unord.multiset/eq.pass.cpp
+++ b/libcxx/test/std/containers/unord/unord.multiset/eq.pass.cpp
@@ -20,10 +20,13 @@
#include <unordered_set>
#include <cassert>
+#include <cstddef>
#include "test_macros.h"
#include "min_allocator.h"
+#include "test_comparisons.h"
+
int main(int, char**)
{
{
@@ -178,5 +181,35 @@ int main(int, char**)
}
#endif
- return 0;
+ // Make sure we take into account the number of times that a key repeats into equality.
+ {
+ int a[] = {1, 1, 1, 2};
+ int b[] = {1, 1, 1, 1, 2};
+
+ std::unordered_multiset<int> c1(std::begin(a), std::end(a));
+ std::unordered_multiset<int> c2(std::begin(b), std::end(b));
+ assert(testEquality(c1, c2, false));
+ }
+
+ // Make sure we behave properly when a custom key predicate is provided.
+ {
+ int a[] = {1, 3};
+ int b[] = {1, 1};
+ // A very poor hash
+ struct HashModuloOddness {
+ std::size_t operator()(int x) const { return std::hash<int>()(x % 2); }
+ };
+ // A very poor hash
+ struct CompareModuloOddness {
+ bool operator()(int x, int y) const { return (x % 2) == (y % 2); }
+ };
+
+ using Set = std::unordered_multiset<int, HashModuloOddness, CompareModuloOddness>;
+ Set c1(std::begin(a), std::end(a));
+ Set c2(std::begin(b), std::end(b));
+
+ assert(testEquality(c1, c2, false));
+ }
+
+ return 0;
}
More information about the libcxx-commits
mailing list