// // Copyright (C) 2022 The Android Open Source Project // // 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 // // http://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 #include #include "common/libs/utils/contains.h" #include "common/libs/utils/unique_resource_allocator.h" #include "common/libs/utils/unique_resource_allocator_test.h" namespace cuttlefish { TEST_P(OneEachTest, GetAnyAvailableOne) { const auto resources = GetParam(); auto allocator = UniqueResourceAllocator::New(resources); if (!allocator) { GTEST_SKIP() << "Memory allocation failed but we aren't testing it."; } std::unordered_set expected_ids{resources.cbegin(), resources.cend()}; using Reservation = UniqueResourceAllocator::Reservation; std::vector allocated; for (int i = 0; i < resources.size(); i++) { auto id_opt = allocator->UniqueItem(); ASSERT_TRUE(id_opt); ASSERT_TRUE(Contains(expected_ids, id_opt->Get())); allocated.emplace_back(std::move(*id_opt)); } ASSERT_FALSE(allocator->UniqueItem()); } INSTANTIATE_TEST_SUITE_P( CvdIdAllocator, OneEachTest, testing::Values(std::vector{}, std::vector{1}, std::vector{1, 22, 3, 43, 5})); TEST_F(CvdIdAllocatorTest, ClaimAll) { std::vector inputs{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; auto allocator = UniqueResourceAllocator::New(inputs); if (!allocator) { GTEST_SKIP() << "Memory allocation failed but we aren't testing it."; } // request inputs.size() items auto allocated_items_opt = allocator->UniqueItems(inputs.size()); ASSERT_TRUE(allocated_items_opt); ASSERT_EQ(allocated_items_opt->size(), inputs.size()); // did it claim all? ASSERT_FALSE(allocator->UniqueItem()); } TEST_F(CvdIdAllocatorTest, StrideBeyond) { std::vector inputs{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; auto allocator = UniqueResourceAllocator::New(inputs); if (!allocator) { GTEST_SKIP() << "Memory allocation failed but we aren't testing it."; } auto three_opt = allocator->UniqueItems(3); auto four_opt = allocator->UniqueItems(4); auto five_opt = allocator->UniqueItems(5); auto two_opt = allocator->UniqueItems(2); auto another_two_opt = allocator->UniqueItems(2); ASSERT_TRUE(three_opt); ASSERT_TRUE(four_opt); ASSERT_FALSE(five_opt); ASSERT_TRUE(two_opt); ASSERT_FALSE(another_two_opt); } TEST_F(CvdIdAllocatorTest, Consecutive) { std::vector inputs{1, 2, 4, 5, 6, 7, 9, 10, 11}; auto allocator = UniqueResourceAllocator::New(inputs); if (!allocator) { GTEST_SKIP() << "Memory allocation failed but we aren't testing it."; } auto four_consecutive = allocator->UniqueConsecutiveItems(4); auto three_consecutive = allocator->UniqueConsecutiveItems(3); auto another_three_consecutive = allocator->UniqueConsecutiveItems(3); auto two_consecutive = allocator->UniqueConsecutiveItems(2); ASSERT_TRUE(four_consecutive); ASSERT_TRUE(three_consecutive); ASSERT_FALSE(another_three_consecutive); ASSERT_TRUE(two_consecutive); // it's empty ASSERT_FALSE(allocator->UniqueItem()) << "one or more left"; } TEST_F(CvdIdAllocatorTest, Take) { std::vector inputs{4, 5, 9}; auto allocator = UniqueResourceAllocator::New(inputs); if (!allocator) { GTEST_SKIP() << "Memory allocation failed but we aren't testing it."; } auto four = allocator->Take(4); auto nine = allocator->Take(9); // wrong auto twenty = allocator->Take(20); ASSERT_TRUE(four); ASSERT_TRUE(nine); ASSERT_FALSE(twenty); } TEST_F(CvdIdAllocatorTest, TakeAll) { std::vector inputs{4, 5, 9, 10}; auto allocator = UniqueResourceAllocator::New(inputs); if (!allocator) { GTEST_SKIP() << "Memory allocation failed but we aren't testing it."; } auto take_4_5_11 = allocator->TakeAll>({4, 5, 11}); auto take_4_5_10 = allocator->TakeAll>({4, 5, 10}); auto take_9_10 = allocator->TakeAll>({9, 10}); auto take_9 = allocator->TakeAll>({9}); ASSERT_FALSE(take_4_5_11); ASSERT_TRUE(take_4_5_10); ASSERT_FALSE(take_9_10); ASSERT_TRUE(take_9); } TEST_F(CvdIdAllocatorTest, TakeRange) { std::vector inputs{1, 2, 4, 5, 6, 7, 8, 9, 10, 11}; auto allocator = UniqueResourceAllocator::New(inputs); if (!allocator) { GTEST_SKIP() << "Memory allocation failed but we aren't testing it."; } auto take_range_5_12 = allocator->TakeRange(5, 12); // shall fail as 3 is missing auto take_range_2_4 = allocator->TakeRange(2, 4); ASSERT_TRUE(take_range_5_12); ASSERT_FALSE(take_range_2_4); } TEST_F(CvdIdAllocatorTest, Reclaim) { std::vector inputs{1, 2, 4, 5, 6, 7, 8, 9, 10, 11}; auto allocator = UniqueResourceAllocator::New(inputs); if (!allocator) { GTEST_SKIP() << "Memory allocation failed but we aren't testing it."; } unsigned one_resource = 0; { auto take_range_5_12 = allocator->TakeRange(5, 12); auto any_single_item = allocator->UniqueItem(); ASSERT_TRUE(take_range_5_12); ASSERT_TRUE(any_single_item); one_resource = any_single_item->Get(); ASSERT_FALSE(allocator->TakeRange(5, 12)); ASSERT_FALSE(allocator->Take(one_resource)); } // take_range_5_12 went out of scope, so resources were reclaimed ASSERT_TRUE(allocator->TakeRange(5, 12)); ASSERT_TRUE(allocator->Take(one_resource)); } TEST(CvdIdAllocatorExpandTest, Expand) { std::vector inputs{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; auto allocator = UniqueResourceAllocator::New(inputs); if (!allocator) { GTEST_SKIP() << "Memory allocation failed but we aren't testing it."; } auto hold_6_to_10 = allocator->TakeRange(6, 11); if (!hold_6_to_10) { GTEST_SKIP() << "TakeRange(6, 11) failed but it's not what is tested here"; } auto expand = allocator->ExpandPool(std::vector{2, 4, 6, 8, 12, 14}); auto take_12 = allocator->Take(12); auto take_14 = allocator->Take(14); auto take_6 = allocator->Take(6); std::vector expected_return_from_expand{2, 4, 6, 8}; ASSERT_EQ(expand, expected_return_from_expand); ASSERT_TRUE(take_12); ASSERT_TRUE(take_14); ASSERT_FALSE(take_6); } } // namespace cuttlefish