PEL: Keep size statistics of PEL repo

Keep a running total of several size statistics of the PEL repository.

The statistics are:
* Total size of all PELs
* Total size of BMC created PELs
* Total size of BMC created informational PELs
* Total size of BMC created non-informational PELs
* Total size of non-BMC created PELs
* Total size of non-BMC created informational PELs
* Total size of non-BMC created non-informational PELs

Here, size refers to the disk size the PEL uses, which is different than
the file size.  The disk size is retrieved from the stat() function and
is the number of 512B blocks used.

The term 'informational' above doesn't strictly refer to the
informational severity value (0x0), but also includes other cases, such
as hidden recovered PELs.

Signed-off-by: Matt Spinler <spinler@us.ibm.com>
Change-Id: I07a3ccd7cfe802a344a2db47daba5fb05d56489f
diff --git a/test/openpower-pels/repository_test.cpp b/test/openpower-pels/repository_test.cpp
index 446e10e..ae88551 100644
--- a/test/openpower-pels/repository_test.cpp
+++ b/test/openpower-pels/repository_test.cpp
@@ -434,3 +434,157 @@
 
     EXPECT_FALSE(fd);
 }
+
+// Test the repo size statistics
+TEST_F(RepositoryTest, TestRepoSizes)
+{
+    uint32_t id = 1;
+
+    Repository repo{repoPath, 10000, 500};
+
+    // All of the size stats are the sizes on disk a PEL takes up,
+    // which is different than the file size.  Disk usage seems
+    // to have a granularity of 4096 bytes.  This probably shouldn't
+    // be hardcoded, but I don't know how to look it up dynamically.
+
+    // All sizes are zero
+    {
+        const auto& stats = repo.getSizeStats();
+        EXPECT_EQ(stats.total, 0);
+        EXPECT_EQ(stats.bmc, 0);
+        EXPECT_EQ(stats.nonBMC, 0);
+        EXPECT_EQ(stats.bmcServiceable, 0);
+        EXPECT_EQ(stats.bmcInfo, 0);
+        EXPECT_EQ(stats.nonBMCServiceable, 0);
+        EXPECT_EQ(stats.nonBMCInfo, 0);
+    }
+
+    // Add a 2000B BMC predictive error
+    auto data = pelFactory(id++, 'O', 0x20, 0x8800, 2000);
+    auto pel = std::make_unique<PEL>(data);
+    auto pelID1 = pel->id();
+    repo.add(pel);
+
+    {
+        const auto& stats = repo.getSizeStats();
+        EXPECT_EQ(stats.total, 4096);
+        EXPECT_EQ(stats.bmc, 4096);
+        EXPECT_EQ(stats.nonBMC, 0);
+        EXPECT_EQ(stats.bmcServiceable, 4096);
+        EXPECT_EQ(stats.bmcInfo, 0);
+        EXPECT_EQ(stats.nonBMCServiceable, 0);
+        EXPECT_EQ(stats.nonBMCInfo, 0);
+    }
+
+    // Add a 5000B BMC informational error
+    data = pelFactory(id++, 'O', 0x00, 0x8800, 5000);
+    pel = std::make_unique<PEL>(data);
+    auto pelID2 = pel->id();
+    repo.add(pel);
+
+    {
+        const auto& stats = repo.getSizeStats();
+        EXPECT_EQ(stats.total, 4096 + 8192);
+        EXPECT_EQ(stats.bmc, 4096 + 8192);
+        EXPECT_EQ(stats.nonBMC, 0);
+        EXPECT_EQ(stats.bmcServiceable, 4096);
+        EXPECT_EQ(stats.bmcInfo, 8192);
+        EXPECT_EQ(stats.nonBMCServiceable, 0);
+        EXPECT_EQ(stats.nonBMCInfo, 0);
+    }
+
+    // Add a 4000B Hostboot unrecoverable error
+    data = pelFactory(id++, 'B', 0x40, 0x8800, 4000);
+    pel = std::make_unique<PEL>(data);
+    auto pelID3 = pel->id();
+    repo.add(pel);
+
+    {
+        const auto& stats = repo.getSizeStats();
+        EXPECT_EQ(stats.total, 4096 + 8192 + 4096);
+        EXPECT_EQ(stats.bmc, 4096 + 8192);
+        EXPECT_EQ(stats.nonBMC, 4096);
+        EXPECT_EQ(stats.bmcServiceable, 4096);
+        EXPECT_EQ(stats.bmcInfo, 8192);
+        EXPECT_EQ(stats.nonBMCServiceable, 4096);
+        EXPECT_EQ(stats.nonBMCInfo, 0);
+    }
+
+    // Add a 5000B Hostboot informational error
+    data = pelFactory(id++, 'B', 0x00, 0x8800, 5000);
+    pel = std::make_unique<PEL>(data);
+    auto pelID4 = pel->id();
+    repo.add(pel);
+
+    {
+        const auto& stats = repo.getSizeStats();
+        EXPECT_EQ(stats.total, 4096 + 8192 + 4096 + 8192);
+        EXPECT_EQ(stats.bmc, 4096 + 8192);
+        EXPECT_EQ(stats.nonBMC, 4096 + 8192);
+        EXPECT_EQ(stats.bmcServiceable, 4096);
+        EXPECT_EQ(stats.bmcInfo, 8192);
+        EXPECT_EQ(stats.nonBMCServiceable, 4096);
+        EXPECT_EQ(stats.nonBMCInfo, 8192);
+    }
+
+    // Remove the BMC serviceable error
+    using ID = Repository::LogID;
+    ID id1{ID::Pel(pelID1)};
+
+    repo.remove(id1);
+    {
+        const auto& stats = repo.getSizeStats();
+        EXPECT_EQ(stats.total, 8192 + 4096 + 8192);
+        EXPECT_EQ(stats.bmc, 8192);
+        EXPECT_EQ(stats.nonBMC, 4096 + 8192);
+        EXPECT_EQ(stats.bmcServiceable, 0);
+        EXPECT_EQ(stats.bmcInfo, 8192);
+        EXPECT_EQ(stats.nonBMCServiceable, 4096);
+        EXPECT_EQ(stats.nonBMCInfo, 8192);
+    }
+
+    // Remove the Hostboot informational error
+    ID id4{ID::Pel(pelID4)};
+
+    repo.remove(id4);
+    {
+        const auto& stats = repo.getSizeStats();
+        EXPECT_EQ(stats.total, 8192 + 4096);
+        EXPECT_EQ(stats.bmc, 8192);
+        EXPECT_EQ(stats.nonBMC, 4096);
+        EXPECT_EQ(stats.bmcServiceable, 0);
+        EXPECT_EQ(stats.bmcInfo, 8192);
+        EXPECT_EQ(stats.nonBMCServiceable, 4096);
+        EXPECT_EQ(stats.nonBMCInfo, 0);
+    }
+
+    // Remove the BMC informational error
+    ID id2{ID::Pel(pelID2)};
+
+    repo.remove(id2);
+    {
+        const auto& stats = repo.getSizeStats();
+        EXPECT_EQ(stats.total, 4096);
+        EXPECT_EQ(stats.bmc, 0);
+        EXPECT_EQ(stats.nonBMC, 4096);
+        EXPECT_EQ(stats.bmcServiceable, 0);
+        EXPECT_EQ(stats.bmcInfo, 0);
+        EXPECT_EQ(stats.nonBMCServiceable, 4096);
+        EXPECT_EQ(stats.nonBMCInfo, 0);
+    }
+
+    // Remove the hostboot unrecoverable error
+    ID id3{ID::Pel(pelID3)};
+
+    repo.remove(id3);
+    {
+        const auto& stats = repo.getSizeStats();
+        EXPECT_EQ(stats.total, 0);
+        EXPECT_EQ(stats.bmc, 0);
+        EXPECT_EQ(stats.nonBMC, 0);
+        EXPECT_EQ(stats.bmcServiceable, 0);
+        EXPECT_EQ(stats.bmcInfo, 0);
+        EXPECT_EQ(stats.nonBMCServiceable, 0);
+        EXPECT_EQ(stats.nonBMCInfo, 0);
+    }
+}