| //===--- unittest/Support/ArrayRecyclerTest.cpp ---------------------------===// |
| // |
| // 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 |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "llvm/Support/ArrayRecycler.h" |
| #include "llvm/Support/Allocator.h" |
| #include "gtest/gtest.h" |
| #include <cstdlib> |
| |
| using namespace llvm; |
| |
| namespace { |
| |
| struct Object { |
| int Num; |
| Object *Other; |
| }; |
| typedef ArrayRecycler<Object> ARO; |
| |
| TEST(ArrayRecyclerTest, Capacity) { |
| // Capacity size should never be 0. |
| ARO::Capacity Cap = ARO::Capacity::get(0); |
| EXPECT_LT(0u, Cap.getSize()); |
| |
| size_t PrevSize = Cap.getSize(); |
| for (unsigned N = 1; N != 100; ++N) { |
| Cap = ARO::Capacity::get(N); |
| EXPECT_LE(N, Cap.getSize()); |
| if (PrevSize >= N) |
| EXPECT_EQ(PrevSize, Cap.getSize()); |
| else |
| EXPECT_LT(PrevSize, Cap.getSize()); |
| PrevSize = Cap.getSize(); |
| } |
| |
| // Check that the buckets are monotonically increasing. |
| Cap = ARO::Capacity::get(0); |
| PrevSize = Cap.getSize(); |
| for (unsigned N = 0; N != 20; ++N) { |
| Cap = Cap.getNext(); |
| EXPECT_LT(PrevSize, Cap.getSize()); |
| PrevSize = Cap.getSize(); |
| } |
| } |
| |
| TEST(ArrayRecyclerTest, Basics) { |
| BumpPtrAllocator Allocator; |
| ArrayRecycler<Object> DUT; |
| |
| ARO::Capacity Cap = ARO::Capacity::get(8); |
| Object *A1 = DUT.allocate(Cap, Allocator); |
| A1[0].Num = 21; |
| A1[7].Num = 17; |
| |
| Object *A2 = DUT.allocate(Cap, Allocator); |
| A2[0].Num = 121; |
| A2[7].Num = 117; |
| |
| Object *A3 = DUT.allocate(Cap, Allocator); |
| A3[0].Num = 221; |
| A3[7].Num = 217; |
| |
| EXPECT_EQ(21, A1[0].Num); |
| EXPECT_EQ(17, A1[7].Num); |
| EXPECT_EQ(121, A2[0].Num); |
| EXPECT_EQ(117, A2[7].Num); |
| EXPECT_EQ(221, A3[0].Num); |
| EXPECT_EQ(217, A3[7].Num); |
| |
| DUT.deallocate(Cap, A2); |
| |
| // Check that deallocation didn't clobber anything. |
| EXPECT_EQ(21, A1[0].Num); |
| EXPECT_EQ(17, A1[7].Num); |
| EXPECT_EQ(221, A3[0].Num); |
| EXPECT_EQ(217, A3[7].Num); |
| |
| // Verify recycling. |
| Object *A2x = DUT.allocate(Cap, Allocator); |
| EXPECT_EQ(A2, A2x); |
| |
| DUT.deallocate(Cap, A2x); |
| DUT.deallocate(Cap, A1); |
| DUT.deallocate(Cap, A3); |
| |
| // Objects are not required to be recycled in reverse deallocation order, but |
| // that is what the current implementation does. |
| Object *A3x = DUT.allocate(Cap, Allocator); |
| EXPECT_EQ(A3, A3x); |
| Object *A1x = DUT.allocate(Cap, Allocator); |
| EXPECT_EQ(A1, A1x); |
| Object *A2y = DUT.allocate(Cap, Allocator); |
| EXPECT_EQ(A2, A2y); |
| |
| // Back to allocation from the BumpPtrAllocator. |
| Object *A4 = DUT.allocate(Cap, Allocator); |
| EXPECT_NE(A1, A4); |
| EXPECT_NE(A2, A4); |
| EXPECT_NE(A3, A4); |
| |
| DUT.clear(Allocator); |
| } |
| |
| } // end anonymous namespace |