[libcxx-commits] [libcxx] [libc++][test] Add exception tests for vector capacity operations (PR #118141)
Peng Liu via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Dec 19 11:51:31 PST 2024
================
@@ -0,0 +1,313 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: no-exceptions
+
+// This test file validates that std::vector<T>::reserve provides a strong exception guarantee if T is
+// Cpp17MoveInsertible and no exception is thrown by the move constructor of T during the reserve call.
+// It also checks that if T's move constructor is not noexcept, reserve provides only a basic exception
+// guarantee.
+
+#include <cstddef>
+#include <memory>
+#include <type_traits>
+#include <vector>
+
+#include "../common.h"
+#include "MoveOnly.h"
+#include "count_new.h"
+#include "increasing_allocator.h"
+#include "min_allocator.h"
+#include "test_allocator.h"
+#include "test_iterators.h"
+#include "test_macros.h"
+
+template <typename T, typename Alloc>
+void test_allocation_exception_for_strong_guarantee(
+ std::vector<T, Alloc>& v, const std::vector<T>& values, std::size_t new_cap) {
+ assert(v.size() == values.size());
+ T* old_data = v.data();
+ std::size_t old_size = v.size();
+ std::size_t old_cap = v.capacity();
+
+ try {
+ v.reserve(new_cap);
+ } catch (...) { // std::length_error, std::bad_alloc
+ assert(v.data() == old_data);
+ assert(v.size() == old_size);
+ assert(v.capacity() == old_cap);
+ for (std::size_t i = 0; i < v.size(); ++i)
+ assert(v[i] == values[i]);
+ }
----------------
winner245 wrote:
Thank you for the suggestion. I agree that making a copy of `v` beforehand would simplify my assertion into one line: `assert(v == copy)`. This approach works for most of the test cases in this PR. However, I find some test cases challenging to apply this method. For example, I have tests covering the `MoveOnly` element type, which disallows me to create a copy beforehand. If I use something like `auto copy = std::move(v)`, `v` would be left in an unspecified state, making subsequent tests on `v` meaningless. This issue becomes more complicated when `MoveOnly` is combined with `throwing_t` to yield the `move_only_throwing_t` element type. Handling these cases may require a separate version of the function for `MoveOnly` and `move_only_throwing_t`, which could defeat the purpose of your suggestion. Therefore, it seems that we may leave the assertion as is. Please let me know if you disagree.
https://github.com/llvm/llvm-project/pull/118141
More information about the libcxx-commits
mailing list