/** * Copyright © 2019 IBM Corporation * * 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 "extensions/openpower-pels/paths.hpp" #include "extensions/openpower-pels/repository.hpp" #include "pel_utils.hpp" #include #include #include using namespace openpower::pels; namespace fs = std::filesystem; /** * Clean the Repo after every testcase. * And because we have PEL object, also clean up * the log ID. */ class RepositoryTest : public CleanLogID { protected: void SetUp() override { repoPath = getPELRepoPath(); } void TearDown() override { fs::remove_all(repoPath); } fs::path repoPath; }; TEST_F(RepositoryTest, FilenameTest) { BCDTime date = {0x20, 0x30, 0x11, 0x28, 0x13, 0x6, 0x7, 0x8}; EXPECT_EQ(Repository::getPELFilename(0x12345678, date), "2030112813060708_12345678"); EXPECT_EQ(Repository::getPELFilename(0xAABBCCDD, date), "2030112813060708_AABBCCDD"); EXPECT_EQ(Repository::getPELFilename(0x3AFF1, date), "2030112813060708_0003AFF1"); EXPECT_EQ(Repository::getPELFilename(100, date), "2030112813060708_00000064"); EXPECT_EQ(Repository::getPELFilename(0, date), "2030112813060708_00000000"); } TEST_F(RepositoryTest, AddTest) { Repository repo{repoPath}; auto data = pelDataFactory(TestPELType::pelSimple); auto pel = std::make_unique(data); repo.add(pel); // Check that the PEL was stored where it was supposed to be, // and that it wrote the PEL data. const auto ts = pel->privateHeader().commitTimestamp(); auto name = Repository::getPELFilename(pel->id(), ts); fs::path file = repoPath / "logs" / name; EXPECT_TRUE(fs::exists(file)); auto newData = readPELFile(file); auto pelData = pel->data(); EXPECT_EQ(*newData, pelData); } TEST_F(RepositoryTest, RestoreTest) { using pelID = Repository::LogID::Pel; using obmcID = Repository::LogID::Obmc; std::vector ids; { Repository repo{repoPath}; // Add some PELs to the repository { auto data = pelDataFactory(TestPELType::pelSimple); auto pel = std::make_unique(data, 1); pel->assignID(); repo.add(pel); ids.emplace_back(pelID(pel->id()), obmcID(1)); } { auto data = pelDataFactory(TestPELType::pelSimple); auto pel = std::make_unique(data, 2); pel->assignID(); repo.add(pel); ids.emplace_back(pelID(pel->id()), obmcID(2)); } // Check they're there EXPECT_TRUE(repo.hasPEL(ids[0])); EXPECT_TRUE(repo.hasPEL(ids[1])); // Do some other search tests while we're here. // Search based on PEL ID Repository::LogID id(pelID(ids[0].pelID)); EXPECT_TRUE(repo.hasPEL(id)); // Search based on OBMC log ID id.pelID.id = 0; id.obmcID = ids[0].obmcID; EXPECT_TRUE(repo.hasPEL(id)); // ... based on the other PEL ID id.pelID = ids[1].pelID; id.obmcID.id = 0; EXPECT_TRUE(repo.hasPEL(id)); // Not found id.pelID.id = 99; id.obmcID.id = 100; EXPECT_FALSE(repo.hasPEL(id)); } { // Restore and check they're still there, then // remove them. Repository repo{repoPath}; EXPECT_TRUE(repo.hasPEL(ids[0])); EXPECT_TRUE(repo.hasPEL(ids[1])); repo.remove(ids[0]); EXPECT_FALSE(repo.hasPEL(ids[0])); repo.remove(ids[1]); EXPECT_FALSE(repo.hasPEL(ids[1])); } } TEST_F(RepositoryTest, TestGetPELData) { using ID = Repository::LogID; Repository repo{repoPath}; ID badID{ID::Pel(42)}; auto noData = repo.getPELData(badID); EXPECT_FALSE(noData); // Add a PEL to the repo, and get the data back with getPELData. auto data = pelDataFactory(TestPELType::pelSimple); auto dataCopy = data; auto pel = std::make_unique(data); auto pelID = pel->id(); repo.add(pel); ID id{ID::Pel(pelID)}; auto pelData = repo.getPELData(id); ASSERT_TRUE(pelData); EXPECT_EQ(dataCopy, *pelData); } TEST_F(RepositoryTest, TestForEach) { Repository repo{repoPath}; // Add 2 PELs auto data = pelDataFactory(TestPELType::pelSimple); auto pel = std::make_unique(data); repo.add(pel); pel = std::make_unique(data); pel->assignID(); pel->setCommitTime(); repo.add(pel); // Make a function that saves the IDs std::vector ids; Repository::ForEachFunc f1 = [&ids](const PEL& pel) { ids.push_back(pel.id()); return false; }; repo.for_each(f1); EXPECT_EQ(ids.size(), 2); // Stop after the first time in. Repository::ForEachFunc f2 = [&ids](const PEL& pel) { ids.push_back(pel.id()); return true; }; ids.clear(); repo.for_each(f2); EXPECT_EQ(ids.size(), 1); } TEST_F(RepositoryTest, TestSubscriptions) { std::vector added; std::vector removed; Repository::AddCallback ac = [&added](const PEL& pel) { added.push_back(pel.id()); }; Repository::DeleteCallback dc = [&removed](uint32_t id) { removed.push_back(id); }; Repository repo{repoPath}; repo.subscribeToAdds("test", ac); repo.subscribeToDeletes("test", dc); auto data = pelDataFactory(TestPELType::pelSimple); auto pel = std::make_unique(data); auto pelID = pel->id(); repo.add(pel); EXPECT_EQ(added.size(), 1); using ID = Repository::LogID; ID id{ID::Pel(pelID)}; repo.remove(id); EXPECT_EQ(removed.size(), 1); repo.unsubscribeFromAdds("test"); repo.unsubscribeFromDeletes("test"); added.clear(); removed.clear(); repo.add(pel); EXPECT_EQ(added.size(), 0); repo.remove(id); EXPECT_EQ(removed.size(), 0); }