// ----------------------------------------------------------------------
// File: ClusterMapTests
// Author: Abhishek Lekshmanan - CERN
// ----------------------------------------------------------------------
/************************************************************************
* EOS - the CERN Disk Storage System *
* Copyright (C) 2023 CERN/Switzerland *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see .*
************************************************************************/
#include "mgm/placement/ClusterMap.hh"
#include "gtest/gtest.h"
TEST(ClusterMgr, default)
{
eos::mgm::placement::ClusterMgr mgr;
//EXPECT_EQ(mgr.getCurrentEpoch(), 0);
EXPECT_FALSE(mgr.getClusterData());
}
TEST(ClusterMgr, addDummyData)
{
eos::mgm::placement::ClusterMgr mgr;
eos::mgm::placement::ClusterData data;
mgr.addClusterData(std::move(data));
//EXPECT_EQ(mgr.getCurrentEpoch(), 1);
EXPECT_TRUE(mgr.getClusterData());
auto d = mgr.getClusterData();
EXPECT_EQ(d->buckets.size(), 0);
EXPECT_EQ(d->disks.size(), 0);
}
TEST(ClusterMgr, addDummyDataTwice)
{
eos::mgm::placement::ClusterMgr mgr;
eos::mgm::placement::ClusterData data1, data2;
mgr.addClusterData(std::move(data1));
mgr.addClusterData(std::move(data2));
//EXPECT_EQ(mgr.getCurrentEpoch(), 2);
EXPECT_TRUE(mgr.getClusterData());
auto d = mgr.getClusterData();
EXPECT_EQ(d->buckets.size(), 0);
EXPECT_EQ(d->disks.size(), 0);
}
TEST(ClusterMgr, StorageHandlerSeq)
{
using namespace eos::mgm::placement;
eos::mgm::placement::ClusterMgr mgr;
{
auto sh = mgr.getStorageHandler();
ASSERT_TRUE(sh.addBucket(get_bucket_type(StdBucketType::ROOT), 0));
ASSERT_TRUE(sh.addBucket(get_bucket_type(StdBucketType::SITE), -1, 0));
ASSERT_TRUE(sh.addBucket(get_bucket_type(StdBucketType::SITE), -2, 0));
ASSERT_TRUE(sh.addBucket(get_bucket_type(StdBucketType::GROUP), -100, -1));
ASSERT_TRUE(sh.addBucket(get_bucket_type(StdBucketType::GROUP), -101, -1));
ASSERT_TRUE(sh.addBucket(get_bucket_type(StdBucketType::GROUP), -102, -2));
ASSERT_TRUE(sh.addDiskSequential(Disk(1), -100));
ASSERT_TRUE(sh.addDiskSequential(Disk(2), -100));
ASSERT_TRUE(sh.addDiskSequential(Disk(3), -101));
ASSERT_TRUE(sh.addDiskSequential(Disk(4), -101));
ASSERT_TRUE(sh.addDiskSequential(Disk(5), -102));
}
//ASSERT_EQ(mgr.getCurrentEpoch(), 1);
auto cluster_data = mgr.getClusterData();
EXPECT_EQ(cluster_data->disks.size(), 5);
EXPECT_EQ(cluster_data->buckets.size(), 256);
auto root_bucket = cluster_data->buckets[0];
std::vector root_items {-1,-2};
EXPECT_EQ(root_bucket.id, 0);
EXPECT_EQ(root_bucket.bucket_type, get_bucket_type(StdBucketType::ROOT));
EXPECT_EQ(root_bucket.items, root_items);
auto site_bucket1 = cluster_data->buckets[1];
std::vector site_items1 {-100,-101};
EXPECT_EQ(site_bucket1.id, -1);
EXPECT_EQ(site_bucket1.bucket_type, get_bucket_type(StdBucketType::SITE));
EXPECT_EQ(site_bucket1.items, site_items1);
auto site_bucket2 = cluster_data->buckets[2];
std::vector site_items2 {-102};
EXPECT_EQ(site_bucket2.id, -2);
EXPECT_EQ(site_bucket2.bucket_type, get_bucket_type(StdBucketType::SITE));
EXPECT_EQ(site_bucket2.items, site_items2);
auto group_bucket1 = cluster_data->buckets[100];
std::vector group_items1 {1,2};
EXPECT_EQ(group_bucket1.id, -100);
EXPECT_EQ(group_bucket1.bucket_type, get_bucket_type(StdBucketType::GROUP));
EXPECT_EQ(group_bucket1.items, group_items1);
auto group_bucket3 = cluster_data->buckets[102];
std::vector group_items3 {5};
EXPECT_EQ(group_bucket3.id, -102);
EXPECT_EQ(group_bucket3.bucket_type, get_bucket_type(StdBucketType::GROUP));
EXPECT_EQ(group_bucket3.items, group_items3);
for (int i=0; i < 5; i++) {
auto disk = cluster_data->disks[i];
EXPECT_EQ(disk.id, i+1);
}
}
TEST(ClusterMgr, StorageHandlerDiskInOrder)
{
using namespace eos::mgm::placement;
eos::mgm::placement::ClusterMgr mgr;
{
auto sh = mgr.getStorageHandler();
ASSERT_TRUE(sh.addBucket(get_bucket_type(StdBucketType::ROOT), 0));
ASSERT_TRUE(sh.addBucket(get_bucket_type(StdBucketType::SITE), -1, 0));
ASSERT_TRUE(sh.addBucket(get_bucket_type(StdBucketType::SITE), -2, 0));
ASSERT_TRUE(sh.addBucket(get_bucket_type(StdBucketType::GROUP), -100, -1));
ASSERT_TRUE(sh.addBucket(get_bucket_type(StdBucketType::GROUP), -101, -1));
ASSERT_TRUE(sh.addBucket(get_bucket_type(StdBucketType::GROUP), -102, -2));
ASSERT_TRUE(sh.addDisk(Disk(1), -100));
ASSERT_TRUE(sh.addDisk(Disk(2), -100));
ASSERT_TRUE(sh.addDisk(Disk(3), -101));
ASSERT_TRUE(sh.addDisk(Disk(4), -101));
ASSERT_TRUE(sh.addDisk(Disk(5), -102));
}
//ASSERT_EQ(mgr.getCurrentEpoch(), 1);
auto cluster_data = mgr.getClusterData();
EXPECT_EQ(cluster_data->disks.size(), 5);
EXPECT_EQ(cluster_data->buckets.size(), 256);
auto root_bucket = cluster_data->buckets[0];
std::vector root_items {-1,-2};
EXPECT_EQ(root_bucket.id, 0);
EXPECT_EQ(root_bucket.bucket_type, get_bucket_type(StdBucketType::ROOT));
EXPECT_EQ(root_bucket.items, root_items);
auto site_bucket1 = cluster_data->buckets[1];
std::vector site_items1 {-100,-101};
EXPECT_EQ(site_bucket1.id, -1);
EXPECT_EQ(site_bucket1.bucket_type, get_bucket_type(StdBucketType::SITE));
EXPECT_EQ(site_bucket1.items, site_items1);
auto site_bucket2 = cluster_data->buckets[2];
std::vector site_items2 {-102};
EXPECT_EQ(site_bucket2.id, -2);
EXPECT_EQ(site_bucket2.bucket_type, get_bucket_type(StdBucketType::SITE));
EXPECT_EQ(site_bucket2.items, site_items2);
auto group_bucket1 = cluster_data->buckets[100];
std::vector group_items1 {1,2};
EXPECT_EQ(group_bucket1.id, -100);
EXPECT_EQ(group_bucket1.bucket_type, get_bucket_type(StdBucketType::GROUP));
EXPECT_EQ(group_bucket1.items, group_items1);
auto group_bucket3 = cluster_data->buckets[102];
std::vector group_items3 {5};
EXPECT_EQ(group_bucket3.id, -102);
EXPECT_EQ(group_bucket3.bucket_type, get_bucket_type(StdBucketType::GROUP));
EXPECT_EQ(group_bucket3.items, group_items3);
for (int i=0; i < 5; i++) {
auto disk = cluster_data->disks[i];
EXPECT_EQ(disk.id, i+1);
}
}
TEST(ClusterMgr, StorageHandlerDisksOutOfOrder)
{
using namespace eos::mgm::placement;
eos::mgm::placement::ClusterMgr mgr;
{
auto sh = mgr.getStorageHandler();
ASSERT_TRUE(sh.addBucket(get_bucket_type(StdBucketType::ROOT), 0));
ASSERT_TRUE(sh.addBucket(get_bucket_type(StdBucketType::SITE), -1, 0));
ASSERT_TRUE(sh.addBucket(get_bucket_type(StdBucketType::SITE), -2, 0));
ASSERT_TRUE(sh.addBucket(get_bucket_type(StdBucketType::GROUP), -100, -1));
ASSERT_TRUE(sh.addBucket(get_bucket_type(StdBucketType::GROUP), -101, -1));
ASSERT_TRUE(sh.addBucket(get_bucket_type(StdBucketType::GROUP), -102, -2));
ASSERT_TRUE(sh.addDisk(Disk(110), -100));
ASSERT_TRUE(sh.addDisk(Disk(100), -100));
ASSERT_TRUE(sh.addDisk(Disk(104), -101));
ASSERT_TRUE(sh.addDisk(Disk(121), -101));
ASSERT_TRUE(sh.addDisk(Disk(150), -102));
}
//ASSERT_EQ(mgr.getCurrentEpoch(), 1);
auto cluster_data = mgr.getClusterData();
EXPECT_EQ(cluster_data->disks.size(), 150);
EXPECT_EQ(cluster_data->buckets.size(), 256);
auto root_bucket = cluster_data->buckets[0];
std::vector root_items{-1, -2};
EXPECT_EQ(root_bucket.id, 0);
EXPECT_EQ(root_bucket.bucket_type, get_bucket_type(StdBucketType::ROOT));
EXPECT_EQ(root_bucket.items, root_items);
auto site_bucket1 = cluster_data->buckets[1];
std::vector site_items1{-100, -101};
EXPECT_EQ(site_bucket1.id, -1);
EXPECT_EQ(site_bucket1.bucket_type, get_bucket_type(StdBucketType::SITE));
EXPECT_EQ(site_bucket1.items, site_items1);
auto site_bucket2 = cluster_data->buckets[2];
std::vector site_items2{-102};
EXPECT_EQ(site_bucket2.id, -2);
EXPECT_EQ(site_bucket2.bucket_type, get_bucket_type(StdBucketType::SITE));
EXPECT_EQ(site_bucket2.items, site_items2);
auto group_bucket1 = cluster_data->buckets[100];
std::vector group_items1{110,100};
EXPECT_EQ(group_bucket1.id, -100);
EXPECT_EQ(group_bucket1.bucket_type, get_bucket_type(StdBucketType::GROUP));
EXPECT_EQ(group_bucket1.items, group_items1);
auto group_bucket2 = cluster_data->buckets[101];
std::vector group_items2{104,121};
EXPECT_EQ(group_bucket2.id, -101);
EXPECT_EQ(group_bucket2.bucket_type, get_bucket_type(StdBucketType::GROUP));
EXPECT_EQ(group_bucket2.items, group_items2);
auto group_bucket3 = cluster_data->buckets[102];
std::vector group_items3{150};
EXPECT_EQ(group_bucket3.id, -102);
EXPECT_EQ(group_bucket3.bucket_type, get_bucket_type(StdBucketType::GROUP));
EXPECT_EQ(group_bucket3.items, group_items3);
}
TEST(ClusterMgr, BM_Layout)
{
using namespace eos::mgm::placement;
eos::mgm::placement::ClusterMgr mgr;
int n_elements = 1024;
int n_disks_per_group = 16;
int n_groups = 32;
{
auto sh = mgr.getStorageHandler(n_elements);
ASSERT_TRUE(sh.addBucket(get_bucket_type(StdBucketType::ROOT), 0));
//ASSERT_TRUE(sh.addBucket(get_bucket_type(StdBucketType::SITE), -1, 0));
for (int i=0; i< n_groups; ++i) {
ASSERT_TRUE(sh.addBucket(get_bucket_type(StdBucketType::GROUP), -100-i, 0));
}
for (int i=0; i < n_groups*n_disks_per_group; i++) {
ASSERT_TRUE(sh.addDisk(Disk(i+1, ConfigStatus::kRW, ActiveStatus::kOnline, 1),
-100 - i/n_disks_per_group));
}
}
auto cluster_data = mgr.getClusterData();
EXPECT_EQ(cluster_data->disks.size(), 32*16);
EXPECT_EQ(cluster_data->buckets.size(), n_elements);
auto root_bucket = cluster_data->buckets[0];
EXPECT_EQ(root_bucket.items.size(), n_groups);
for (auto it: root_bucket.items) {
EXPECT_EQ(cluster_data->buckets.at(-it).items.size(), n_disks_per_group);
}
}