Add RecordManager testcases

These will test the linear conversion as well
as record queue management.

Change-Id: I94e80e0d51f889e8ca2aef7c9c9c17e86153f5e3
Signed-off-by: Matt Spinler <spinler@us.ibm.com>
diff --git a/Makefile.am b/Makefile.am
index fd4cd96..87250db 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -34,4 +34,4 @@
 	@mkdir -p `dirname $@`
 	$(SDBUSPLUSPLUS) -r $(srcdir) error exception-cpp org.open_power.Witherspoon.Fault > $@
 
-SUBDIRS = . power-sequencer power-supply test
+SUBDIRS = . power-sequencer power-supply test power-supply/test
diff --git a/configure.ac b/configure.ac
index d13af6f..9d38bcc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -74,5 +74,5 @@
 )
 
 # Create configured output
-AC_CONFIG_FILES([Makefile power-sequencer/Makefile power-supply/Makefile test/Makefile])
+AC_CONFIG_FILES([Makefile power-sequencer/Makefile power-supply/Makefile test/Makefile power-supply/test/Makefile])
 AC_OUTPUT
diff --git a/power-supply/test/Makefile.am b/power-supply/test/Makefile.am
new file mode 100644
index 0000000..95fbca0
--- /dev/null
+++ b/power-supply/test/Makefile.am
@@ -0,0 +1,24 @@
+AM_CPPFLAGS = -I$(top_srcdir)
+
+# Run all 'check' test programs
+TESTS = $(check_PROGRAMS)
+
+check_PROGRAMS = test_records
+
+test_records_CPPFLAGS = -Igtest $(GTEST_CPPFLAGS) $(AM_CPPFLAGS)
+
+test_records_CXXFLAGS = $(PTHREAD_CFLAGS) \
+	$(PHOSPHOR_DBUS_INTERFACES_CFLAGS) \
+	$(PHOSPHOR_LOGGING_CFLAGS) \
+	$(SDBUSPLUS_CFLAGS)
+
+test_records_LDFLAGS = -lgtest_main -lgtest \
+	$(PTHREAD_LIBS) $(OESDK_TESTCASE_FLAGS) \
+	$(PHOSPHOR_DBUS_INTERFACES_LIBS) \
+	$(PHOSPHOR_LOGGING_LIBS) \
+	$(SDBUSPLUS_LIBS)
+
+test_records_SOURCES = test_records.cpp
+
+test_records_LDADD = ../record_manager.o
+
diff --git a/power-supply/test/test_records.cpp b/power-supply/test/test_records.cpp
new file mode 100644
index 0000000..20b638b
--- /dev/null
+++ b/power-supply/test/test_records.cpp
@@ -0,0 +1,182 @@
+/**
+ * Copyright © 2017 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 <gtest/gtest.h>
+#include <iostream>
+#include "names_values.hpp"
+#include "../record_manager.hpp"
+
+using namespace witherspoon::power::history;
+
+/**
+ * Test the linearToInteger function with different
+ * combinations of positive and negative mantissas and
+ * exponents.
+ *
+ * Value = mantissa * 2**exponent
+ */
+TEST(LinearFormatTest, TestConversions)
+{
+    //Mantissa > 0, exponent = 0
+    EXPECT_EQ(0, RecordManager::linearToInteger(0));
+    EXPECT_EQ(1, RecordManager::linearToInteger(1));
+    EXPECT_EQ(38, RecordManager::linearToInteger(0x26));
+    EXPECT_EQ(1023, RecordManager::linearToInteger(0x3FF));
+
+    //Mantissa < 0, exponent = 0
+    EXPECT_EQ(-1, RecordManager::linearToInteger(0x7FF));
+    EXPECT_EQ(-20, RecordManager::linearToInteger(0x7EC));
+    EXPECT_EQ(-769, RecordManager::linearToInteger(0x4FF));
+    EXPECT_EQ(-989, RecordManager::linearToInteger(0x423));
+    EXPECT_EQ(-1024, RecordManager::linearToInteger(0x400));
+
+    //Mantissa >= 0, exponent > 0
+    //M = 1, E = 2
+    EXPECT_EQ(4, RecordManager::linearToInteger(0x1001));
+
+    //M = 1000, E = 10
+    EXPECT_EQ(1024000, RecordManager::linearToInteger(0x53E8));
+
+    //M = 10, E = 15
+    EXPECT_EQ(327680, RecordManager::linearToInteger(0x780A));
+
+    //Mantissa >= 0, exponent < 0
+    //M = 0, E = -1
+    EXPECT_EQ(0, RecordManager::linearToInteger(0xF800));
+
+    //M = 100, E = -2
+    EXPECT_EQ(25, RecordManager::linearToInteger(0xF064));
+
+    //Mantissa < 0, exponent < 0
+    //M = -100, E = -1
+    EXPECT_EQ(-50, RecordManager::linearToInteger(0xFF9C));
+
+    //M = -1024, E = -7
+    EXPECT_EQ(-8, RecordManager::linearToInteger(0xCC00));
+}
+
+/**
+ * @brief Helper function to create a record buffer
+ *
+ * @param sequenceID - the ID to use
+ * @param avgPower - the average power, in linear format
+ * @param maxPower - the max power, in linear format
+ *
+ * @return vector<uint8_t> the record buffer
+ */
+std::vector<uint8_t> makeRawRecord(
+        uint8_t sequenceID,
+        uint16_t avgPower,
+        uint16_t maxPower)
+{
+    std::vector<uint8_t> record;
+
+    record.push_back(sequenceID);
+    record.push_back(avgPower & 0xFF);
+    record.push_back(avgPower >> 8);
+    record.push_back(maxPower & 0xFF);
+    record.push_back(maxPower >> 8);
+
+    return record;
+}
+
+
+/**
+ * Test record queue management
+ */
+TEST(ManagerTest, TestRecordAdds)
+{
+    //Hold 5 max records.  IDs roll over at 8.
+    RecordManager mgr{5, 8};
+
+    EXPECT_EQ(0, mgr.getNumRecords());
+
+    mgr.add(makeRawRecord(0, 0, 0));
+    EXPECT_EQ(1, mgr.getNumRecords());
+
+    mgr.add(makeRawRecord(1, 0, 0));
+    EXPECT_EQ(2, mgr.getNumRecords());
+
+    mgr.add(makeRawRecord(2, 0, 0));
+    EXPECT_EQ(3, mgr.getNumRecords());
+
+    mgr.add(makeRawRecord(3, 0, 0));
+    EXPECT_EQ(4, mgr.getNumRecords());
+
+    mgr.add(makeRawRecord(4, 0, 0));
+    EXPECT_EQ(5, mgr.getNumRecords());
+
+    //start pruning
+    mgr.add(makeRawRecord(5, 0, 0));
+    EXPECT_EQ(5, mgr.getNumRecords());
+
+    mgr.add(makeRawRecord(6, 0, 0));
+    EXPECT_EQ(5, mgr.getNumRecords());
+
+    mgr.add(makeRawRecord(7, 0, 0));
+    EXPECT_EQ(5, mgr.getNumRecords());
+
+    mgr.add(makeRawRecord(8, 0, 0));
+    EXPECT_EQ(5, mgr.getNumRecords());
+
+    //rollover
+    mgr.add(makeRawRecord(0, 0, 0));
+    EXPECT_EQ(5, mgr.getNumRecords());
+
+    mgr.add(makeRawRecord(1, 0, 0));
+    EXPECT_EQ(5, mgr.getNumRecords());
+
+    //nonsequential ID, clear previous
+    mgr.add(makeRawRecord(4, 0, 10));
+    EXPECT_EQ(1, mgr.getNumRecords());
+
+    //back to normal
+    mgr.add(makeRawRecord(5, 1, 11));
+    EXPECT_EQ(2, mgr.getNumRecords());
+
+    //One more good record
+    mgr.add(makeRawRecord(6, 2, 12));
+    EXPECT_EQ(3, mgr.getNumRecords());
+
+    //Add a garbage length record. No size change
+    mgr.add(std::vector<uint8_t>(6, 0));
+    EXPECT_EQ(3, mgr.getNumRecords());
+
+    //Test the DBus Records
+    auto avgRecords = mgr.getAverageRecords();
+    EXPECT_EQ(3, avgRecords.size());
+
+    auto maxRecords = mgr.getMaximumRecords();
+    EXPECT_EQ(3, maxRecords.size());
+
+    auto avg = 2;
+    for (const auto& r : avgRecords)
+    {
+        EXPECT_EQ(avg, std::get<1>(r));
+        avg--;
+    }
+
+    auto max = 12;
+    for (const auto& r : maxRecords)
+    {
+        EXPECT_EQ(max, std::get<1>(r));
+        max--;
+    }
+
+    //Add a zero length record. Records cleared.
+    mgr.add(std::vector<uint8_t>{});
+    EXPECT_EQ(0, mgr.getNumRecords());
+}
+