/************************************************************************
* EOS - the CERN Disk Storage System *
* Copyright (C) 2016 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 .*
************************************************************************/
//------------------------------------------------------------------------------
//! @author Georgios Bitzes
//! @breif NextInodeProvider tests
//------------------------------------------------------------------------------
#include "namespace/ns_quarkdb/persistency/NextInodeProvider.hh"
#include "TestUtils.hh"
#include "qclient/structures/QHash.hh"
#include "Namespace.hh"
#include
#include
EOSNSTESTING_BEGIN
class NextInodeProviderTest : public NsTestsFixture {};
TEST_F(NextInodeProviderTest, BasicSanity)
{
std::unique_ptr qcl = createQClient();
qclient::QHash myhash;
myhash.setKey("ns-tests-next-inode-provider");
myhash.setClient(*qcl.get());
myhash.hdel("counter");
constexpr size_t firstRunLimit = 50000;
constexpr size_t secondRunLimit = 100000;
{
NextInodeProvider inodeProvider;
inodeProvider.configure(myhash, "counter");
for (size_t i = 1; i < firstRunLimit; i++) {
ASSERT_EQ(inodeProvider.getFirstFreeId(), i);
ASSERT_EQ(inodeProvider.reserve(), i);
}
}
{
NextInodeProvider inodeProvider;
inodeProvider.configure(myhash, "counter");
size_t continuation = inodeProvider.getFirstFreeId();
ASSERT_TRUE(firstRunLimit <= continuation);
std::cerr << "Wasted " << continuation - firstRunLimit << " inodes." <<
std::endl;
for (size_t i = continuation; i < secondRunLimit; i++) {
ASSERT_EQ(inodeProvider.getFirstFreeId(), i);
ASSERT_EQ(inodeProvider.reserve(), i);
}
}
qcl->del("ns-tests-next-inode-provider");
}
TEST_F(NextInodeProviderTest, Blacklisting)
{
std::unique_ptr qcl = createQClient();
qclient::QHash myhash;
myhash.setKey("ns-tests-next-inode-provider");
myhash.setClient(*qcl.get());
myhash.hdel("counter");
NextInodeProvider inodeProvider;
inodeProvider.configure(myhash, "counter");
ASSERT_EQ(inodeProvider.reserve(), 1);
ASSERT_EQ(inodeProvider.reserve(), 2);
ASSERT_EQ(inodeProvider.reserve(), 3);
inodeProvider.blacklistBelow(4);
ASSERT_EQ("4", myhash.hget("counter"));
ASSERT_EQ(inodeProvider.reserve(), 5);
ASSERT_EQ(inodeProvider.reserve(), 6);
ASSERT_EQ(inodeProvider.reserve(), 7);
inodeProvider.blacklistBelow(1);
inodeProvider.blacklistBelow(6);
inodeProvider.blacklistBelow(7);
for(size_t i = 8; i < 5000; i++) {
ASSERT_EQ(inodeProvider.reserve(), i);
}
inodeProvider.blacklistBelow(10000);
ASSERT_EQ("10000", myhash.hget("counter"));
for(size_t i = 10001; i < 10100; i++) {
ASSERT_EQ(inodeProvider.reserve(), i);
}
}
TEST(InodeBlock, BasicSanity) {
int64_t ino = 0;
InodeBlock block(1, 0);
ASSERT_TRUE(block.empty());
ASSERT_FALSE(block.reserve(ino));
ASSERT_FALSE(block.getFirstFreeID(ino));
block = InodeBlock(1, -1);
ASSERT_TRUE(block.empty());
ASSERT_FALSE(block.reserve(ino));
ASSERT_FALSE(block.getFirstFreeID(ino));
block = InodeBlock(1, 1);
ASSERT_FALSE(block.empty());
ASSERT_TRUE(block.getFirstFreeID(ino));
ASSERT_EQ(ino, 1);
ASSERT_TRUE(block.reserve(ino));
ASSERT_EQ(ino, 1);
ASSERT_TRUE(block.empty());
block = InodeBlock(9, 3);
ASSERT_FALSE(block.empty());
for(int64_t i = 9; i < 9+3; i++) {
ASSERT_TRUE(block.getFirstFreeID(ino));
ASSERT_EQ(ino, i);
ASSERT_TRUE(block.reserve(ino));
ASSERT_EQ(ino, i);
}
ASSERT_TRUE(block.empty());
}
TEST(InodeBlock, Blacklisting) {
int64_t ino = 0;
InodeBlock block(10, 10);
ASSERT_FALSE(block.empty());
block.blacklistBelow(9);
ASSERT_TRUE(block.reserve(ino));
ASSERT_EQ(ino, 10);
block.blacklistBelow(11);
ASSERT_TRUE(block.reserve(ino));
ASSERT_EQ(ino, 12);
block.blacklistBelow(11);
ASSERT_TRUE(block.reserve(ino));
ASSERT_EQ(ino, 13);
block.blacklistBelow(18);
ASSERT_TRUE(block.reserve(ino));
ASSERT_EQ(ino, 19);
ASSERT_FALSE(block.reserve(ino));
ASSERT_TRUE(block.empty());
}
TEST(InodeBlock, BlacklistingAll) {
int64_t ino = 0;
InodeBlock block(10, 10);
ASSERT_FALSE(block.empty());
block.blacklistBelow(19);
ASSERT_TRUE(block.empty());
block = InodeBlock(10, 10);
ASSERT_FALSE(block.empty());
block.blacklistBelow(20);
ASSERT_TRUE(block.empty());
block = InodeBlock(10, 10);
ASSERT_FALSE(block.empty());
block.blacklistBelow(18);
ASSERT_TRUE(block.reserve(ino));
ASSERT_EQ(ino, 19);
ASSERT_TRUE(block.empty());
}
TEST_F(NextInodeProviderTest, BlacklistingOffByOne)
{
std::unique_ptr qcl = createQClient();
qclient::QHash myhash;
myhash.setKey("ns-tests-next-inode-provider");
myhash.setClient(*qcl.get());
myhash.hdel("counter");
std::unique_ptr inodeProvider;
inodeProvider.reset(new NextInodeProvider());
inodeProvider->configure(myhash, "counter");
inodeProvider->blacklistBelow(4294967296);
ASSERT_EQ(inodeProvider->reserve(), 4294967297);
inodeProvider.reset(new NextInodeProvider());
inodeProvider->configure(myhash, "counter");
inodeProvider->blacklistBelow(4294967296);
ASSERT_EQ(inodeProvider->reserve(), 4294967298);
ASSERT_EQ(inodeProvider->reserve(), 4294967299);
ASSERT_EQ(inodeProvider->reserve(), 4294967300);
ASSERT_EQ(inodeProvider->reserve(), 4294967301);
inodeProvider.reset(new NextInodeProvider());
inodeProvider->configure(myhash, "counter");
inodeProvider->blacklistBelow(4294967296);
ASSERT_EQ(inodeProvider->reserve(), 4294967304);
}
TEST_F(NextInodeProviderTest, MultipleResets)
{
std::unique_ptr qcl = createQClient();
qclient::QHash myhash;
myhash.setKey("ns-tests-next-inode-provider");
myhash.setClient(*qcl.get());
myhash.hdel("counter");
std::unique_ptr inodeProvider;
inodeProvider.reset(new NextInodeProvider());
inodeProvider->configure(myhash, "counter");
ASSERT_EQ(inodeProvider->reserve(), 1);
inodeProvider->blacklistBelow(-10);
ASSERT_EQ(inodeProvider->reserve(), 2);
inodeProvider->blacklistBelow(2);
ASSERT_EQ(inodeProvider->reserve(), 3);
ASSERT_EQ("3", myhash.hget("counter"));
inodeProvider.reset(new NextInodeProvider());
inodeProvider->configure(myhash, "counter");
inodeProvider->blacklistBelow(3);
ASSERT_EQ("3", myhash.hget("counter"));
ASSERT_EQ(inodeProvider->reserve(), 4);
ASSERT_EQ(inodeProvider->reserve(), 5);
ASSERT_EQ(inodeProvider->reserve(), 6);
ASSERT_EQ(inodeProvider->reserve(), 7);
inodeProvider->blacklistBelow(7);
ASSERT_EQ("9", myhash.hget("counter"));
inodeProvider.reset(new NextInodeProvider());
inodeProvider->configure(myhash, "counter");
ASSERT_EQ("9", myhash.hget("counter"));
inodeProvider->blacklistBelow(9);
ASSERT_EQ(inodeProvider->reserve(), 10);
ASSERT_EQ("10", myhash.hget("counter"));
}
EOSNSTESTING_END