mirror of
https://github.com/fmtlib/fmt.git
synced 2025-09-10 13:13:57 -04:00
Add test cases for the updated move ctor
- Added two test cases `move_ctor_inline_buffer_non_propagating` and `move_ctor_dynamic_buffer_non_propagating` - Added `PropageteOnMove` template parameter to `allocator_ref` class to be compatible with the old test cases - `allocator_ref` now implements `!=` and `==` operators
This commit is contained in:
parent
a543d79c5c
commit
b15bbdcb23
@ -307,7 +307,7 @@ TEST(memory_buffer_test, ctor) {
|
|||||||
EXPECT_EQ(123u, buffer.capacity());
|
EXPECT_EQ(123u, buffer.capacity());
|
||||||
}
|
}
|
||||||
|
|
||||||
using std_allocator = allocator_ref<std::allocator<char>>;
|
using std_allocator = allocator_ref<std::allocator<char>, true>;
|
||||||
|
|
||||||
TEST(memory_buffer_test, move_ctor_inline_buffer) {
|
TEST(memory_buffer_test, move_ctor_inline_buffer) {
|
||||||
auto check_move_buffer =
|
auto check_move_buffer =
|
||||||
@ -351,6 +351,53 @@ TEST(memory_buffer_test, move_ctor_dynamic_buffer) {
|
|||||||
EXPECT_GT(buffer2.capacity(), 4u);
|
EXPECT_GT(buffer2.capacity(), 4u);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using std_allocator_n = allocator_ref<std::allocator<char>, false>;
|
||||||
|
|
||||||
|
TEST(memory_buffer_test, move_ctor_inline_buffer_non_propagating) {
|
||||||
|
auto check_move_buffer =
|
||||||
|
[](const char* str,
|
||||||
|
basic_memory_buffer<char, 5, std_allocator_n>& buffer) {
|
||||||
|
std::allocator<char>* original_alloc_ptr = buffer.get_allocator().get();
|
||||||
|
basic_memory_buffer<char, 5, std_allocator_n> buffer2(
|
||||||
|
std::move(buffer));
|
||||||
|
EXPECT_EQ(str, std::string(&buffer[0], buffer.size()));
|
||||||
|
EXPECT_EQ(str, std::string(&buffer2[0], buffer2.size()));
|
||||||
|
EXPECT_EQ(5u, buffer2.capacity());
|
||||||
|
// Allocators should NOT be transferred; they remain distinct instances.
|
||||||
|
// The original buffer's allocator pointer should still be valid (not
|
||||||
|
// nullptr).
|
||||||
|
EXPECT_EQ(original_alloc_ptr, buffer.get_allocator().get());
|
||||||
|
EXPECT_NE(original_alloc_ptr, buffer2.get_allocator().get());
|
||||||
|
};
|
||||||
|
auto alloc = std::allocator<char>();
|
||||||
|
basic_memory_buffer<char, 5, std_allocator_n> buffer(
|
||||||
|
(std_allocator_n(&alloc)));
|
||||||
|
const char test[] = "test";
|
||||||
|
buffer.append(string_view(test, 4));
|
||||||
|
check_move_buffer("test", buffer);
|
||||||
|
buffer.push_back('a');
|
||||||
|
check_move_buffer("testa", buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(memory_buffer_test, move_ctor_dynamic_buffer_non_propagating) {
|
||||||
|
auto alloc = std::allocator<char>();
|
||||||
|
basic_memory_buffer<char, 4, std_allocator_n> buffer(
|
||||||
|
(std_allocator_n(&alloc)));
|
||||||
|
const char test[] = "test";
|
||||||
|
buffer.append(test, test + 4);
|
||||||
|
const char* inline_buffer_ptr = &buffer[0];
|
||||||
|
buffer.push_back('a');
|
||||||
|
EXPECT_NE(&buffer[0], inline_buffer_ptr);
|
||||||
|
std::allocator<char>* original_alloc_ptr = buffer.get_allocator().get();
|
||||||
|
basic_memory_buffer<char, 4, std_allocator_n> buffer2(std::move(buffer));
|
||||||
|
EXPECT_EQ(buffer.size(), 0);
|
||||||
|
EXPECT_EQ(std::string(&buffer2[0], buffer2.size()), "testa");
|
||||||
|
EXPECT_GT(buffer2.capacity(), 4u);
|
||||||
|
EXPECT_NE(&buffer2[0], inline_buffer_ptr);
|
||||||
|
EXPECT_EQ(original_alloc_ptr, buffer.get_allocator().get());
|
||||||
|
EXPECT_NE(original_alloc_ptr, buffer2.get_allocator().get());
|
||||||
|
}
|
||||||
|
|
||||||
void check_move_assign_buffer(const char* str,
|
void check_move_assign_buffer(const char* str,
|
||||||
basic_memory_buffer<char, 5>& buffer) {
|
basic_memory_buffer<char, 5>& buffer) {
|
||||||
basic_memory_buffer<char, 5> buffer2;
|
basic_memory_buffer<char, 5> buffer2;
|
||||||
|
@ -37,7 +37,8 @@ template <typename T> class mock_allocator {
|
|||||||
MOCK_METHOD(void, deallocate, (T*, size_t));
|
MOCK_METHOD(void, deallocate, (T*, size_t));
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Allocator> class allocator_ref {
|
template <typename Allocator, bool PropagateOnMove = false>
|
||||||
|
class allocator_ref {
|
||||||
private:
|
private:
|
||||||
Allocator* alloc_;
|
Allocator* alloc_;
|
||||||
|
|
||||||
@ -48,6 +49,9 @@ template <typename Allocator> class allocator_ref {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
using value_type = typename Allocator::value_type;
|
using value_type = typename Allocator::value_type;
|
||||||
|
using propagate_on_container_move_assignment =
|
||||||
|
typename std::conditional<PropagateOnMove, std::true_type,
|
||||||
|
std::false_type>::type;
|
||||||
|
|
||||||
explicit allocator_ref(Allocator* alloc = nullptr) : alloc_(alloc) {}
|
explicit allocator_ref(Allocator* alloc = nullptr) : alloc_(alloc) {}
|
||||||
|
|
||||||
@ -73,14 +77,16 @@ template <typename Allocator> class allocator_ref {
|
|||||||
}
|
}
|
||||||
void deallocate(value_type* p, size_t n) { alloc_->deallocate(p, n); }
|
void deallocate(value_type* p, size_t n) { alloc_->deallocate(p, n); }
|
||||||
|
|
||||||
friend bool operator==(const allocator_ref& a, const allocator_ref& b) noexcept {
|
friend bool operator==(const allocator_ref& a,
|
||||||
|
const allocator_ref& b) noexcept {
|
||||||
if (a.alloc_ == b.alloc_) return true;
|
if (a.alloc_ == b.alloc_) return true;
|
||||||
if (a.alloc_ == nullptr || b.alloc_ == nullptr) return false;
|
if (a.alloc_ == nullptr || b.alloc_ == nullptr) return false;
|
||||||
|
|
||||||
return *a.alloc_ == *b.alloc_;
|
return *a.alloc_ == *b.alloc_;
|
||||||
}
|
}
|
||||||
|
|
||||||
friend bool operator!=(const allocator_ref& a, const allocator_ref& b) noexcept {
|
friend bool operator!=(const allocator_ref& a,
|
||||||
|
const allocator_ref& b) noexcept {
|
||||||
return !(a == b);
|
return !(a == b);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user