blob: 88ab2a9357c36ec25c78163955804b1b7acfa07f [file] [log] [blame]
//
// 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 <unordered_set>
#include <vector>
#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<unsigned>::New(resources);
if (!allocator) {
GTEST_SKIP() << "Memory allocation failed but we aren't testing it.";
}
std::unordered_set<unsigned> expected_ids{resources.cbegin(),
resources.cend()};
using Reservation = UniqueResourceAllocator<unsigned>::Reservation;
std::vector<Reservation> 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<unsigned>{}, std::vector<unsigned>{1},
std::vector<unsigned>{1, 22, 3, 43, 5}));
TEST_F(CvdIdAllocatorTest, ClaimAll) {
std::vector<unsigned> inputs{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
auto allocator = UniqueResourceAllocator<unsigned>::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<unsigned> inputs{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
auto allocator = UniqueResourceAllocator<unsigned>::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<unsigned> inputs{1, 2, 4, 5, 6, 7, 9, 10, 11};
auto allocator = UniqueResourceAllocator<unsigned>::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<unsigned> inputs{4, 5, 9};
auto allocator = UniqueResourceAllocator<unsigned>::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<unsigned> inputs{4, 5, 9, 10};
auto allocator = UniqueResourceAllocator<unsigned>::New(inputs);
if (!allocator) {
GTEST_SKIP() << "Memory allocation failed but we aren't testing it.";
}
auto take_4_5_11 = allocator->TakeAll<std::vector<unsigned>>({4, 5, 11});
auto take_4_5_10 = allocator->TakeAll<std::vector<unsigned>>({4, 5, 10});
auto take_9_10 = allocator->TakeAll<std::vector<unsigned>>({9, 10});
auto take_9 = allocator->TakeAll<std::vector<unsigned>>({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<unsigned> inputs{1, 2, 4, 5, 6, 7, 8, 9, 10, 11};
auto allocator = UniqueResourceAllocator<unsigned>::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<unsigned> inputs{1, 2, 4, 5, 6, 7, 8, 9, 10, 11};
auto allocator = UniqueResourceAllocator<unsigned>::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<unsigned> inputs{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
auto allocator = UniqueResourceAllocator<unsigned>::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<unsigned>{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<unsigned> 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