blob: 070741924cb8b81efc984a5051886d0e1e37c938 [file] [log] [blame]
// Copyright 2023 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
#include "pw_allocator/tracking_allocator.h"
#include "pw_allocator/allocator_testing.h"
#include "pw_unit_test/framework.h"
namespace pw::allocator {
namespace {
constexpr static size_t kCapacity = 256;
TEST(TrackingAllocatorTest, AutomaticInit_Metrics) {
WithBuffer<SimpleAllocator, kCapacity> allocator;
TrackingAllocatorImpl<internal::Metrics> tracker(
test::kToken, *allocator, kCapacity);
internal::Metrics& group = tracker.metric_group();
EXPECT_EQ(group.metrics().size(), 9U);
EXPECT_EQ(group.children().size(), 0U);
EXPECT_TRUE(tracker.initialized());
}
TEST(TrackingAllocatorTest, AutomaticInit_MetricsStub) {
WithBuffer<SimpleAllocator, kCapacity> allocator;
TrackingAllocatorImpl<internal::MetricsStub> tracker(
test::kToken, *allocator, kCapacity);
EXPECT_TRUE(tracker.initialized());
}
TEST(TrackingAllocatorTest, ManualInit_Metrics) {
WithBuffer<SimpleAllocator, kCapacity> allocator;
TrackingAllocatorImpl<internal::Metrics> tracker(test::kToken);
internal::Metrics& group = tracker.metric_group();
EXPECT_EQ(group.metrics().size(), 0U);
EXPECT_EQ(group.children().size(), 0U);
EXPECT_FALSE(tracker.initialized());
tracker.Init(*allocator, kCapacity);
EXPECT_EQ(group.metrics().size(), 9U);
EXPECT_EQ(group.children().size(), 0U);
EXPECT_TRUE(tracker.initialized());
}
TEST(TrackingAllocatorTest, ManualInit_MetricsStub) {
WithBuffer<SimpleAllocator, kCapacity> allocator;
TrackingAllocatorImpl<internal::MetricsStub> tracker(test::kToken);
EXPECT_FALSE(tracker.initialized());
tracker.Init(*allocator, kCapacity);
EXPECT_TRUE(tracker.initialized());
}
TEST(TrackingAllocatorTest, NoInit_Metrics) {
WithBuffer<SimpleAllocator, kCapacity> allocator;
TrackingAllocatorImpl<internal::Metrics> tracker(test::kToken);
Layout layout = Layout::Of<std::byte>();
EXPECT_EQ(tracker.Allocate(layout), nullptr);
tracker.Deallocate(nullptr, layout);
EXPECT_FALSE(tracker.Resize(nullptr, layout, 2));
EXPECT_EQ(tracker.Reallocate(nullptr, layout, 2), nullptr);
}
TEST(TrackingAllocatorTest, NoInit_MetricsStub) {
WithBuffer<SimpleAllocator, kCapacity> allocator;
TrackingAllocatorImpl<internal::MetricsStub> tracker(test::kToken);
Layout layout = Layout::Of<std::byte>();
EXPECT_EQ(tracker.Allocate(layout), nullptr);
tracker.Deallocate(nullptr, layout);
EXPECT_FALSE(tracker.Resize(nullptr, layout, 2));
EXPECT_EQ(tracker.Reallocate(nullptr, layout, 2), nullptr);
}
// These unit tests below use `AllocatorForTest<kBufferSize>`, which forwards
// `Allocator` calls to a `TrackingAllocatorImpl<internal::Metrics>` field. This
// is the same type as `TrackingAllocator`, except that metrics are explicitly
// enabled. As a result, these unit tests do validate `TrackingAllocator`, even
// when that type never appears directly in a test.
TEST(TrackingAllocatorTest, InitialValues) {
test::AllocatorForTest<kCapacity> allocator;
EXPECT_EQ(allocator.total_bytes(), kCapacity);
EXPECT_EQ(allocator.allocated_bytes(), 0U);
EXPECT_EQ(allocator.peak_allocated_bytes(), 0U);
EXPECT_EQ(allocator.cumulative_allocated_bytes(), 0U);
EXPECT_EQ(allocator.num_allocations(), 0U);
EXPECT_EQ(allocator.num_deallocations(), 0U);
EXPECT_EQ(allocator.num_resizes(), 0U);
EXPECT_EQ(allocator.num_reallocations(), 0U);
EXPECT_EQ(allocator.num_failures(), 0U);
}
TEST(TrackingAllocatorTest, AllocateDeallocate) {
test::AllocatorForTest<kCapacity> allocator;
constexpr Layout layout = Layout::Of<uint32_t[2]>();
void* ptr = allocator.Allocate(layout);
ASSERT_NE(ptr, nullptr);
EXPECT_EQ(allocator.total_bytes(), kCapacity);
EXPECT_EQ(allocator.allocated_bytes(), sizeof(uint32_t) * 2);
EXPECT_EQ(allocator.peak_allocated_bytes(), sizeof(uint32_t) * 2);
EXPECT_EQ(allocator.cumulative_allocated_bytes(), sizeof(uint32_t) * 2);
EXPECT_EQ(allocator.num_allocations(), 1U);
EXPECT_EQ(allocator.num_deallocations(), 0U);
EXPECT_EQ(allocator.num_resizes(), 0U);
EXPECT_EQ(allocator.num_reallocations(), 0U);
EXPECT_EQ(allocator.num_failures(), 0U);
allocator.Deallocate(ptr, layout);
EXPECT_EQ(allocator.total_bytes(), kCapacity);
EXPECT_EQ(allocator.allocated_bytes(), 0U);
EXPECT_EQ(allocator.peak_allocated_bytes(), sizeof(uint32_t) * 2);
EXPECT_EQ(allocator.cumulative_allocated_bytes(), sizeof(uint32_t) * 2);
EXPECT_EQ(allocator.num_allocations(), 1U);
EXPECT_EQ(allocator.num_deallocations(), 1U);
EXPECT_EQ(allocator.num_resizes(), 0U);
EXPECT_EQ(allocator.num_reallocations(), 0U);
EXPECT_EQ(allocator.num_failures(), 0U);
}
TEST(TrackingAllocatorTest, AllocateFailure) {
test::AllocatorForTest<kCapacity> allocator;
constexpr Layout layout = Layout::Of<uint32_t[0x10000000U]>();
void* ptr = allocator.Allocate(layout);
EXPECT_EQ(ptr, nullptr);
EXPECT_EQ(allocator.total_bytes(), kCapacity);
EXPECT_EQ(allocator.allocated_bytes(), 0U);
EXPECT_EQ(allocator.peak_allocated_bytes(), 0U);
EXPECT_EQ(allocator.cumulative_allocated_bytes(), 0U);
EXPECT_EQ(allocator.num_allocations(), 0U);
EXPECT_EQ(allocator.num_deallocations(), 0U);
EXPECT_EQ(allocator.num_resizes(), 0U);
EXPECT_EQ(allocator.num_reallocations(), 0U);
EXPECT_EQ(allocator.num_failures(), 1U);
}
TEST(TrackingAllocatorTest, AllocateDeallocateMultiple) {
test::AllocatorForTest<kCapacity> allocator;
constexpr Layout layout1 = Layout::Of<uint32_t[3]>();
void* ptr1 = allocator.Allocate(layout1);
ASSERT_NE(ptr1, nullptr);
EXPECT_EQ(allocator.total_bytes(), kCapacity);
EXPECT_EQ(allocator.allocated_bytes(), sizeof(uint32_t) * 3);
EXPECT_EQ(allocator.peak_allocated_bytes(), sizeof(uint32_t) * 3);
EXPECT_EQ(allocator.cumulative_allocated_bytes(), sizeof(uint32_t) * 3);
EXPECT_EQ(allocator.num_allocations(), 1U);
EXPECT_EQ(allocator.num_deallocations(), 0U);
EXPECT_EQ(allocator.num_resizes(), 0U);
EXPECT_EQ(allocator.num_reallocations(), 0U);
EXPECT_EQ(allocator.num_failures(), 0U);
constexpr Layout layout2 = Layout::Of<uint32_t[2]>();
void* ptr2 = allocator.Allocate(layout2);
ASSERT_NE(ptr2, nullptr);
EXPECT_EQ(allocator.total_bytes(), kCapacity);
EXPECT_EQ(allocator.allocated_bytes(), sizeof(uint32_t) * 5);
EXPECT_EQ(allocator.peak_allocated_bytes(), sizeof(uint32_t) * 5);
EXPECT_EQ(allocator.cumulative_allocated_bytes(), sizeof(uint32_t) * 5);
EXPECT_EQ(allocator.num_allocations(), 2U);
EXPECT_EQ(allocator.num_deallocations(), 0U);
EXPECT_EQ(allocator.num_resizes(), 0U);
EXPECT_EQ(allocator.num_reallocations(), 0U);
EXPECT_EQ(allocator.num_failures(), 0U);
allocator.Deallocate(ptr1, layout1);
EXPECT_EQ(allocator.total_bytes(), kCapacity);
EXPECT_EQ(allocator.allocated_bytes(), sizeof(uint32_t) * 2);
EXPECT_EQ(allocator.peak_allocated_bytes(), sizeof(uint32_t) * 5);
EXPECT_EQ(allocator.cumulative_allocated_bytes(), sizeof(uint32_t) * 5);
EXPECT_EQ(allocator.num_allocations(), 2U);
EXPECT_EQ(allocator.num_deallocations(), 1U);
EXPECT_EQ(allocator.num_resizes(), 0U);
EXPECT_EQ(allocator.num_reallocations(), 0U);
EXPECT_EQ(allocator.num_failures(), 0U);
constexpr Layout layout3 = Layout::Of<uint32_t>();
void* ptr3 = allocator.Allocate(layout3);
ASSERT_NE(ptr3, nullptr);
EXPECT_EQ(allocator.total_bytes(), kCapacity);
EXPECT_EQ(allocator.allocated_bytes(), sizeof(uint32_t) * 3);
EXPECT_EQ(allocator.peak_allocated_bytes(), sizeof(uint32_t) * 5);
EXPECT_EQ(allocator.cumulative_allocated_bytes(), sizeof(uint32_t) * 6);
EXPECT_EQ(allocator.num_allocations(), 3U);
EXPECT_EQ(allocator.num_deallocations(), 1U);
EXPECT_EQ(allocator.num_resizes(), 0U);
EXPECT_EQ(allocator.num_reallocations(), 0U);
EXPECT_EQ(allocator.num_failures(), 0U);
allocator.Deallocate(ptr3, layout3);
EXPECT_EQ(allocator.total_bytes(), kCapacity);
EXPECT_EQ(allocator.allocated_bytes(), sizeof(uint32_t) * 2);
EXPECT_EQ(allocator.peak_allocated_bytes(), sizeof(uint32_t) * 5);
EXPECT_EQ(allocator.cumulative_allocated_bytes(), sizeof(uint32_t) * 6);
EXPECT_EQ(allocator.num_allocations(), 3U);
EXPECT_EQ(allocator.num_deallocations(), 2U);
EXPECT_EQ(allocator.num_resizes(), 0U);
EXPECT_EQ(allocator.num_reallocations(), 0U);
EXPECT_EQ(allocator.num_failures(), 0U);
allocator.Deallocate(ptr2, layout2);
EXPECT_EQ(allocator.total_bytes(), kCapacity);
EXPECT_EQ(allocator.allocated_bytes(), 0U);
EXPECT_EQ(allocator.peak_allocated_bytes(), sizeof(uint32_t) * 5);
EXPECT_EQ(allocator.cumulative_allocated_bytes(), sizeof(uint32_t) * 6);
EXPECT_EQ(allocator.num_allocations(), 3U);
EXPECT_EQ(allocator.num_deallocations(), 3U);
EXPECT_EQ(allocator.num_resizes(), 0U);
EXPECT_EQ(allocator.num_reallocations(), 0U);
EXPECT_EQ(allocator.num_failures(), 0U);
}
TEST(TrackingAllocatorTest, ResizeLarger) {
test::AllocatorForTest<kCapacity> allocator;
constexpr Layout old_layout = Layout::Of<uint32_t[3]>();
void* ptr = allocator.Allocate(old_layout);
ASSERT_NE(ptr, nullptr);
EXPECT_EQ(allocator.total_bytes(), kCapacity);
EXPECT_EQ(allocator.allocated_bytes(), sizeof(uint32_t) * 3);
EXPECT_EQ(allocator.peak_allocated_bytes(), sizeof(uint32_t) * 3);
EXPECT_EQ(allocator.cumulative_allocated_bytes(), sizeof(uint32_t) * 3);
EXPECT_EQ(allocator.num_allocations(), 1U);
EXPECT_EQ(allocator.num_deallocations(), 0U);
EXPECT_EQ(allocator.num_resizes(), 0U);
EXPECT_EQ(allocator.num_reallocations(), 0U);
EXPECT_EQ(allocator.num_failures(), 0U);
constexpr Layout new_layout = Layout::Of<uint32_t[5]>();
EXPECT_TRUE(allocator.Resize(ptr, old_layout, new_layout.size()));
EXPECT_EQ(allocator.total_bytes(), kCapacity);
EXPECT_EQ(allocator.allocated_bytes(), sizeof(uint32_t) * 5);
EXPECT_EQ(allocator.peak_allocated_bytes(), sizeof(uint32_t) * 5);
EXPECT_EQ(allocator.cumulative_allocated_bytes(), sizeof(uint32_t) * 5);
EXPECT_EQ(allocator.num_allocations(), 1U);
EXPECT_EQ(allocator.num_deallocations(), 0U);
EXPECT_EQ(allocator.num_resizes(), 1U);
EXPECT_EQ(allocator.num_reallocations(), 0U);
EXPECT_EQ(allocator.num_failures(), 0U);
allocator.Deallocate(ptr, new_layout);
EXPECT_EQ(allocator.total_bytes(), kCapacity);
EXPECT_EQ(allocator.allocated_bytes(), 0U);
EXPECT_EQ(allocator.peak_allocated_bytes(), sizeof(uint32_t) * 5);
EXPECT_EQ(allocator.cumulative_allocated_bytes(), sizeof(uint32_t) * 5);
EXPECT_EQ(allocator.num_allocations(), 1U);
EXPECT_EQ(allocator.num_deallocations(), 1U);
EXPECT_EQ(allocator.num_resizes(), 1U);
EXPECT_EQ(allocator.num_reallocations(), 0U);
EXPECT_EQ(allocator.num_failures(), 0U);
}
TEST(TrackingAllocatorTest, ResizeSmaller) {
test::AllocatorForTest<kCapacity> allocator;
constexpr Layout old_layout = Layout::Of<uint32_t[2]>();
void* ptr = allocator.Allocate(old_layout);
ASSERT_NE(ptr, nullptr);
EXPECT_EQ(allocator.total_bytes(), kCapacity);
EXPECT_EQ(allocator.allocated_bytes(), sizeof(uint32_t) * 2);
EXPECT_EQ(allocator.peak_allocated_bytes(), sizeof(uint32_t) * 2);
EXPECT_EQ(allocator.cumulative_allocated_bytes(), sizeof(uint32_t) * 2);
EXPECT_EQ(allocator.num_allocations(), 1U);
EXPECT_EQ(allocator.num_deallocations(), 0U);
EXPECT_EQ(allocator.num_resizes(), 0U);
EXPECT_EQ(allocator.num_reallocations(), 0U);
EXPECT_EQ(allocator.num_failures(), 0U);
constexpr Layout new_layout = Layout::Of<uint32_t>();
EXPECT_TRUE(allocator.Resize(ptr, old_layout, new_layout.size()));
EXPECT_EQ(allocator.total_bytes(), kCapacity);
EXPECT_EQ(allocator.allocated_bytes(), sizeof(uint32_t));
EXPECT_EQ(allocator.peak_allocated_bytes(), sizeof(uint32_t) * 2);
EXPECT_EQ(allocator.cumulative_allocated_bytes(), sizeof(uint32_t) * 2);
EXPECT_EQ(allocator.num_allocations(), 1U);
EXPECT_EQ(allocator.num_deallocations(), 0U);
EXPECT_EQ(allocator.num_resizes(), 1U);
EXPECT_EQ(allocator.num_reallocations(), 0U);
EXPECT_EQ(allocator.num_failures(), 0U);
allocator.Deallocate(ptr, new_layout);
EXPECT_EQ(allocator.total_bytes(), kCapacity);
EXPECT_EQ(allocator.allocated_bytes(), 0U);
EXPECT_EQ(allocator.peak_allocated_bytes(), sizeof(uint32_t) * 2);
EXPECT_EQ(allocator.cumulative_allocated_bytes(), sizeof(uint32_t) * 2);
EXPECT_EQ(allocator.num_allocations(), 1U);
EXPECT_EQ(allocator.num_deallocations(), 1U);
EXPECT_EQ(allocator.num_resizes(), 1U);
EXPECT_EQ(allocator.num_reallocations(), 0U);
EXPECT_EQ(allocator.num_failures(), 0U);
}
TEST(TrackingAllocatorTest, ResizeFailure) {
test::AllocatorForTest<kCapacity> allocator;
constexpr Layout layout = Layout::Of<uint32_t[2]>();
void* ptr1 = allocator.Allocate(layout);
ASSERT_NE(ptr1, nullptr);
void* ptr2 = allocator.Allocate(layout);
ASSERT_NE(ptr2, nullptr);
EXPECT_EQ(allocator.total_bytes(), kCapacity);
EXPECT_EQ(allocator.allocated_bytes(), sizeof(uint32_t) * 4);
EXPECT_EQ(allocator.peak_allocated_bytes(), sizeof(uint32_t) * 4);
EXPECT_EQ(allocator.cumulative_allocated_bytes(), sizeof(uint32_t) * 4);
EXPECT_EQ(allocator.num_allocations(), 2U);
EXPECT_EQ(allocator.num_deallocations(), 0U);
EXPECT_EQ(allocator.num_resizes(), 0U);
EXPECT_EQ(allocator.num_reallocations(), 0U);
EXPECT_EQ(allocator.num_failures(), 0U);
EXPECT_FALSE(allocator.Resize(ptr1, layout, layout.size() * 2));
EXPECT_EQ(allocator.total_bytes(), kCapacity);
EXPECT_EQ(allocator.allocated_bytes(), sizeof(uint32_t) * 4);
EXPECT_EQ(allocator.peak_allocated_bytes(), sizeof(uint32_t) * 4);
EXPECT_EQ(allocator.cumulative_allocated_bytes(), sizeof(uint32_t) * 4);
EXPECT_EQ(allocator.num_allocations(), 2U);
EXPECT_EQ(allocator.num_deallocations(), 0U);
EXPECT_EQ(allocator.num_resizes(), 0U);
EXPECT_EQ(allocator.num_reallocations(), 0U);
EXPECT_EQ(allocator.num_failures(), 1U);
}
TEST(TrackingAllocatorTest, Reallocate) {
test::AllocatorForTest<kCapacity> allocator;
constexpr Layout layout1 = Layout::Of<uint32_t[2]>();
void* ptr1 = allocator.Allocate(layout1);
ASSERT_NE(ptr1, nullptr);
EXPECT_EQ(allocator.total_bytes(), kCapacity);
EXPECT_EQ(allocator.allocated_bytes(), sizeof(uint32_t) * 2);
EXPECT_EQ(allocator.peak_allocated_bytes(), sizeof(uint32_t) * 2);
EXPECT_EQ(allocator.cumulative_allocated_bytes(), sizeof(uint32_t) * 2);
EXPECT_EQ(allocator.num_allocations(), 1U);
EXPECT_EQ(allocator.num_deallocations(), 0U);
EXPECT_EQ(allocator.num_resizes(), 0U);
EXPECT_EQ(allocator.num_reallocations(), 0U);
EXPECT_EQ(allocator.num_failures(), 0U);
// If `Reallocate` just resizes, no extra memory is allocated
constexpr Layout layout2 = Layout::Of<uint32_t[4]>();
void* new_ptr1 = allocator.Reallocate(ptr1, layout1, layout2.size());
EXPECT_EQ(new_ptr1, ptr1);
EXPECT_EQ(allocator.total_bytes(), kCapacity);
EXPECT_EQ(allocator.allocated_bytes(), sizeof(uint32_t) * 4);
EXPECT_EQ(allocator.peak_allocated_bytes(), sizeof(uint32_t) * 4);
EXPECT_EQ(allocator.cumulative_allocated_bytes(), sizeof(uint32_t) * 4);
EXPECT_EQ(allocator.num_allocations(), 1U);
EXPECT_EQ(allocator.num_deallocations(), 0U);
EXPECT_EQ(allocator.num_resizes(), 0U);
EXPECT_EQ(allocator.num_reallocations(), 1U);
EXPECT_EQ(allocator.num_failures(), 0U);
// Make a second allocation to force reallocation.
void* ptr2 = allocator.Allocate(layout1);
ASSERT_NE(ptr2, nullptr);
EXPECT_EQ(allocator.total_bytes(), kCapacity);
EXPECT_EQ(allocator.allocated_bytes(), sizeof(uint32_t) * 6);
EXPECT_EQ(allocator.peak_allocated_bytes(), sizeof(uint32_t) * 6);
EXPECT_EQ(allocator.cumulative_allocated_bytes(), sizeof(uint32_t) * 6);
EXPECT_EQ(allocator.num_allocations(), 2U);
EXPECT_EQ(allocator.num_deallocations(), 0U);
EXPECT_EQ(allocator.num_resizes(), 0U);
EXPECT_EQ(allocator.num_reallocations(), 1U);
EXPECT_EQ(allocator.num_failures(), 0U);
// If `Reallocate` must copy to a new location, it allocates before
// deallocating and results in higher peaks.
constexpr Layout layout3 = Layout::Of<uint32_t[8]>();
new_ptr1 = allocator.Reallocate(ptr1, layout2, layout3.size());
EXPECT_NE(new_ptr1, ptr1);
EXPECT_EQ(allocator.total_bytes(), kCapacity);
EXPECT_EQ(allocator.allocated_bytes(), sizeof(uint32_t) * 10);
EXPECT_EQ(allocator.peak_allocated_bytes(), sizeof(uint32_t) * 14);
EXPECT_EQ(allocator.cumulative_allocated_bytes(), sizeof(uint32_t) * 14);
EXPECT_EQ(allocator.num_allocations(), 2U);
EXPECT_EQ(allocator.num_deallocations(), 0U);
EXPECT_EQ(allocator.num_resizes(), 0U);
EXPECT_EQ(allocator.num_reallocations(), 2U);
EXPECT_EQ(allocator.num_failures(), 0U);
allocator.Deallocate(ptr2, layout1);
allocator.Deallocate(new_ptr1, layout3);
EXPECT_EQ(allocator.total_bytes(), kCapacity);
EXPECT_EQ(allocator.allocated_bytes(), 0U);
EXPECT_EQ(allocator.peak_allocated_bytes(), sizeof(uint32_t) * 14);
EXPECT_EQ(allocator.cumulative_allocated_bytes(), sizeof(uint32_t) * 14);
EXPECT_EQ(allocator.num_allocations(), 2U);
EXPECT_EQ(allocator.num_deallocations(), 2U);
EXPECT_EQ(allocator.num_resizes(), 0U);
EXPECT_EQ(allocator.num_reallocations(), 2U);
EXPECT_EQ(allocator.num_failures(), 0U);
}
TEST(TrackingAllocatorTest, ReallocateFailure) {
test::AllocatorForTest<kCapacity> allocator;
constexpr Layout layout = Layout::Of<uint32_t[4]>();
void* ptr1 = allocator.Allocate(layout);
ASSERT_NE(ptr1, nullptr);
EXPECT_EQ(allocator.total_bytes(), kCapacity);
EXPECT_EQ(allocator.allocated_bytes(), sizeof(uint32_t) * 4);
EXPECT_EQ(allocator.peak_allocated_bytes(), sizeof(uint32_t) * 4);
EXPECT_EQ(allocator.cumulative_allocated_bytes(), sizeof(uint32_t) * 4);
EXPECT_EQ(allocator.num_allocations(), 1U);
EXPECT_EQ(allocator.num_deallocations(), 0U);
EXPECT_EQ(allocator.num_resizes(), 0U);
EXPECT_EQ(allocator.num_reallocations(), 0U);
EXPECT_EQ(allocator.num_failures(), 0U);
void* ptr2 = allocator.Reallocate(ptr1, layout, 0x10000000U);
EXPECT_EQ(ptr2, nullptr);
EXPECT_EQ(allocator.total_bytes(), kCapacity);
EXPECT_EQ(allocator.allocated_bytes(), sizeof(uint32_t) * 4);
EXPECT_EQ(allocator.peak_allocated_bytes(), sizeof(uint32_t) * 4);
EXPECT_EQ(allocator.cumulative_allocated_bytes(), sizeof(uint32_t) * 4);
EXPECT_EQ(allocator.num_allocations(), 1U);
EXPECT_EQ(allocator.num_deallocations(), 0U);
EXPECT_EQ(allocator.num_resizes(), 0U);
EXPECT_EQ(allocator.num_reallocations(), 0U);
EXPECT_EQ(allocator.num_failures(), 1U);
}
} // namespace
} // namespace pw::allocator