-
Notifications
You must be signed in to change notification settings - Fork 1.6k
<flat_meow>: Add tests for all flat_map constructors, deduction guides and then some
#6000
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
StephanTLavavej
merged 49 commits into
microsoft:feature/flat_map
from
vmichal:test-flat-meow
Jan 11, 2026
Merged
Changes from all commits
Commits
Show all changes
49 commits
Select commit
Hold shift + click to select a range
c06daba
Test that hints given to `flat_multiset::emplace_hint` and `insert` a…
vmichal 08f6af5
Test that hints given to `flat_multimap::emplace_hint` and `insert` a…
vmichal e24412d
Add more tests for flat_set::erase.
vmichal 355c391
Refactor existing flat_map construction tests - use all codepaths (in…
vmichal ba114e6
Refactor existing flat_map allocator construction tests - add allocat…
vmichal 439980b
Add tests for flat_map construction from (iter, iter), initializer_li…
vmichal 386b1f4
Reword fixme regarding missing flat_map construction tests.
vmichal 5139e7a
Unify checks that flat_map and flat_multimap accept their dedicated _…
vmichal 21838ca
Generalize flat_map erase_if and swap tests for various containers.
vmichal 8a4dd86
Remove explicitly specified template arguments in flat_set constructo…
vmichal 804dc74
Merge branch 'feature/flat_map' into test-flat-meow
vmichal da13b30
Fix typo
vmichal 70c9c33
Test that heterogeneous lookup works with transparent comparator that…
vmichal f3b0642
Don't optimize heterogeneous when key is not of key_type.
vmichal 99d9892
Properly use flat_set deduction guides in tests.
vmichal ee5e510
Reduce scope of previously-global type alias in flat_set tests.
vmichal a157e32
Add death tests for all asserts in <flat_set>
vmichal c94b5e2
Add death tests for all asserts in <flat_map>
vmichal 3673606
Separate death tests into logical groups by what type of violation th…
vmichal 1c1e240
Test that heterogeneous flat_map lookup operations don't attempt to c…
vmichal 2ff469a
Extract code testing container requirements from flat_set test into a…
vmichal 72a7967
Refactor requirements on flat_map to use checks shared with flat_set.
vmichal 652e37b
Improve printing of causes of failing tests for containers that don't…
vmichal d8e6812
Fix three-way-comparability test
vmichal 047ee85
Check invariants and requirements of more flat_map objects in tests
vmichal 513f799
Remove using namespace std from the shared test header, add std:: qua…
vmichal 65dc3c4
Fix typo: Check invariants of correct container. Properly compare ref…
vmichal c402040
flat_set::reference should not be mutable. Make it the same type as f…
vmichal 5b14ad2
Revert "flat_set::reference should not be mutable. Make it the same t…
vmichal 2ab424f
Container *begin() may return reference or const_reference (as is the…
vmichal e51799e
Improve comments.
StephanTLavavej 637ab36
Include more headers.
StephanTLavavej 62f38a3
Down with typename.
StephanTLavavej 14f0159
Remove unused and shadowing `struct is_nothrow_swappable`.
StephanTLavavej 3d87da6
Use aliases.
StephanTLavavej 3e2958c
Avoid shadowing: `empty` => `my_empty`
StephanTLavavej 15dc457
`template <typename T>` => `template <class T>`
StephanTLavavej 7ee5304
Increase strictness.
StephanTLavavej 0877fbc
Add const.
StephanTLavavej da4b643
Test const overloading.
StephanTLavavej 615f456
Consistently order key_container_type before mapped_container_type.
StephanTLavavej a01e682
Use `adjacent_find()` to check uniqueness.
StephanTLavavej 0a78e60
`std::declval` => `declval`
StephanTLavavej cf5a3f8
Use `lt` alias.
StephanTLavavej 5510f60
West const.
StephanTLavavej 5c584ec
`_STD` => `std::`, `_RANGES` => `ranges::`
StephanTLavavej f2a0049
`assert_check_content` => `check_content`, mark check functions as `[…
StephanTLavavej d7af0bd
Drop bogus commented-out tuple_size specialization.
StephanTLavavej 96ca5f7
Construct temporaries with braces.
StephanTLavavej File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,189 @@ | ||
| // Copyright (c) Microsoft Corporation. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
|
|
||
| #pragma once | ||
|
|
||
| #include <algorithm> | ||
| #include <cassert> | ||
| #include <compare> | ||
| #include <format> | ||
| #include <iterator> | ||
| #include <print> | ||
| #include <type_traits> | ||
| #include <utility> | ||
|
|
||
| // Extracted common functionality from flat_map and flat_set tests. | ||
| // May be extended for other containers if needed. | ||
|
|
||
| template <class T> | ||
| void assert_container_requirements(const T& s) { | ||
| T m = s; | ||
| assert(m == s); | ||
|
|
||
| static_assert(std::is_same_v<decltype(m = s), T&>); | ||
| static_assert(std::is_same_v<decltype(m = std::move(m)), T&>); | ||
| static_assert(std::is_same_v<decltype(m.begin()), typename T::iterator>); | ||
| static_assert(std::is_same_v<decltype(m.end()), typename T::iterator>); | ||
| static_assert(std::is_same_v<decltype(s.begin()), typename T::const_iterator>); | ||
| static_assert(std::is_same_v<decltype(s.end()), typename T::const_iterator>); | ||
| static_assert(std::is_same_v<decltype(m.cbegin()), typename T::const_iterator>); | ||
| static_assert(std::is_same_v<decltype(m.cend()), typename T::const_iterator>); | ||
| static_assert(std::is_same_v<decltype(s.cbegin()), typename T::const_iterator>); | ||
| static_assert(std::is_same_v<decltype(s.cend()), typename T::const_iterator>); | ||
| static_assert(std::is_convertible_v<typename T::iterator, typename T::const_iterator>); | ||
| static_assert(std::is_same_v<decltype(m.begin() <=> m.end()), std::strong_ordering>); | ||
| static_assert(std::is_same_v<decltype(s.size()), typename T::size_type>); | ||
| static_assert(std::is_same_v<decltype(s.max_size()), typename T::size_type>); | ||
| static_assert(std::is_same_v<decltype(*m.begin()), typename T::reference> | ||
| || std::is_same_v<decltype(*m.begin()), typename T::const_reference>); | ||
| static_assert(std::is_same_v<decltype(*m.cbegin()), typename T::const_reference>); | ||
|
|
||
| T my_moved = std::move(m); | ||
| assert(!(my_moved != s)); | ||
|
|
||
| T my_empty{}; | ||
| assert(my_empty.empty()); | ||
|
|
||
| T non_empty = s; | ||
| my_empty.swap(non_empty); | ||
| assert(non_empty.empty()); | ||
| assert(my_empty == s); | ||
|
|
||
| std::swap(my_empty, non_empty); | ||
| assert(my_empty.empty()); | ||
| assert(non_empty == s); | ||
|
|
||
| assert(s.cbegin() <= s.cend()); | ||
| assert((s.cbegin() < s.cend()) == !s.empty()); | ||
|
|
||
| assert(m.begin() <= m.end()); | ||
| assert((m.begin() < m.end()) == !m.empty()); | ||
|
|
||
| assert(static_cast<T::size_type>(s.cend() - s.cbegin()) == s.size()); | ||
| } | ||
|
|
||
| template <class T> | ||
| void assert_reversible_container_requirements(const T& s) { | ||
| static_assert(std::is_same_v<std::reverse_iterator<typename T::iterator>, typename T::reverse_iterator>); | ||
| static_assert( | ||
| std::is_same_v<std::reverse_iterator<typename T::const_iterator>, typename T::const_reverse_iterator>); | ||
| static_assert(std::is_same_v<decltype(T{}.rbegin()), typename T::reverse_iterator>); | ||
| static_assert(std::is_same_v<decltype(T{}.rend()), typename T::reverse_iterator>); | ||
| static_assert(std::is_same_v<decltype(s.rbegin()), typename T::const_reverse_iterator>); | ||
| static_assert(std::is_same_v<decltype(s.rend()), typename T::const_reverse_iterator>); | ||
| static_assert(std::is_same_v<decltype(T{}.crbegin()), typename T::const_reverse_iterator>); | ||
| static_assert(std::is_same_v<decltype(T{}.crend()), typename T::const_reverse_iterator>); | ||
| static_assert(std::is_same_v<decltype(s.crbegin()), typename T::const_reverse_iterator>); | ||
| static_assert(std::is_same_v<decltype(s.crend()), typename T::const_reverse_iterator>); | ||
| static_assert(std::is_convertible_v<typename T::reverse_iterator, typename T::const_reverse_iterator>); | ||
| } | ||
|
|
||
| template <class T> | ||
| concept map_has_nothrow_swappable_containers = requires { | ||
| typename T::key_container_type; | ||
| typename T::mapped_container_type; | ||
| requires std::is_nothrow_swappable_v<typename T::key_container_type>; | ||
| requires std::is_nothrow_swappable_v<typename T::mapped_container_type>; | ||
| }; | ||
|
|
||
| template <class T> | ||
| concept set_has_nothrow_swappable_containers = requires { | ||
| typename T::container_type; | ||
| requires std::is_nothrow_swappable_v<typename T::container_type>; | ||
| }; | ||
|
|
||
| template <class T> | ||
| concept has_nothrow_swappable_containers = | ||
| set_has_nothrow_swappable_containers<T> || map_has_nothrow_swappable_containers<T>; | ||
|
|
||
| template <class T> | ||
| void assert_noexcept_requirements(T& s) { | ||
| static_assert(noexcept(s.begin())); | ||
| static_assert(noexcept(s.end())); | ||
| static_assert(noexcept(s.cbegin())); | ||
| static_assert(noexcept(s.cend())); | ||
| static_assert(noexcept(s.rbegin())); | ||
| static_assert(noexcept(s.rend())); | ||
| static_assert(noexcept(s.crbegin())); | ||
| static_assert(noexcept(s.crend())); | ||
|
|
||
| static_assert(noexcept(s.empty())); | ||
| static_assert(noexcept(s.size())); | ||
| static_assert(noexcept(s.max_size())); | ||
|
|
||
| if constexpr (!std::is_const_v<T>) { | ||
| constexpr bool is_noexcept = | ||
| has_nothrow_swappable_containers<T> && std::is_nothrow_swappable_v<typename T::key_compare>; | ||
| static_assert(noexcept(s.swap(s)) == is_noexcept); | ||
| static_assert(noexcept(std::ranges::swap(s, s)) == is_noexcept); // using ADL-swap | ||
| static_assert(noexcept(s.clear())); | ||
| } | ||
| } | ||
|
|
||
| template <bool ExpectedUnique, class T> | ||
| void assert_is_sorted_maybe_unique(const T& s) { | ||
| const auto val_comp = s.value_comp(); | ||
| const auto begin_it = s.cbegin(); | ||
| const auto end_it = s.cend(); | ||
|
|
||
| // internal check by the container itself | ||
| assert(s._Is_sorted_and_unique()); | ||
|
|
||
| // external check observable by the user | ||
| assert(std::is_sorted(begin_it, end_it, val_comp)); | ||
StephanTLavavej marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| if constexpr (ExpectedUnique) { | ||
| const auto not_comp = [&](const auto& left, const auto& right) { return !val_comp(left, right); }; | ||
| const bool is_unique = std::adjacent_find(begin_it, end_it, not_comp) == end_it; | ||
|
|
||
| if constexpr (std::formattable<T, char>) { | ||
| if (!is_unique) { | ||
| std::println("Container {} is not unique", s); | ||
| } | ||
| } | ||
| assert(is_unique); | ||
| } | ||
| } | ||
|
|
||
| template <class T> | ||
| void assert_set_requirements() { | ||
| using iterator = T::iterator; | ||
| using const_iterator = T::const_iterator; | ||
| using key_type = T::key_type; | ||
| using value_type = T::value_type; | ||
| using reference = T::reference; | ||
| using const_reference = T::const_reference; | ||
|
|
||
| static_assert(std::same_as<std::const_iterator<const_iterator>, const_iterator>); | ||
| static_assert(std::is_convertible_v<iterator, const_iterator>); | ||
|
|
||
| // additionally: | ||
| static_assert(std::is_same_v<key_type, value_type>); | ||
| static_assert(std::same_as<std::const_iterator<iterator>, iterator>); | ||
| static_assert(std::is_convertible_v<const_iterator, iterator>); | ||
| static_assert(std::is_same_v<decltype(*std::declval<T>().begin()), const value_type&>); | ||
| static_assert(std::is_same_v<std::remove_cvref_t<reference>, value_type>); | ||
| static_assert(std::is_same_v<const_reference, const value_type&>); | ||
| } | ||
|
|
||
| template <class T> | ||
| void assert_map_requirements() { | ||
| using iterator = T::iterator; | ||
| using const_iterator = T::const_iterator; | ||
| using key_type = T::key_type; | ||
| using value_type = T::value_type; | ||
| using mapped_type = T::mapped_type; | ||
|
|
||
| static_assert(std::same_as<std::const_iterator<const_iterator>, const_iterator>); | ||
| static_assert(std::is_convertible_v<iterator, const_iterator>); | ||
|
|
||
| // additionally: | ||
| static_assert(std::is_same_v<value_type, std::pair<key_type, mapped_type>>); | ||
| } | ||
|
|
||
| template <class T> | ||
| void assert_three_way_comparability() { | ||
| using value_type = T::value_type; | ||
| if constexpr (std::three_way_comparable<value_type>) { | ||
| static_assert(std::three_way_comparable<T>); | ||
| } | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.