PEL: Validate the Action Flags field

According to the PEL spec, the Action Flags and Event Type fields in the
User Header section must be in agreement with the Severity field. So,
when a PEL is being created from an OpenBMC event log, check those
values for correctness and fix them up if required.

In addition, as those fields are optional in the message registry, this
code will also just set these two fields to valid values if they were
left out.

The rules being followed are documented in the PEL readme.

Signed-off-by: Matt Spinler <spinler@us.ibm.com>
Change-Id: Iad88de5080ba79a9ff31f962ef99bfc11994b9ed
diff --git a/test/openpower-pels/Makefile.include b/test/openpower-pels/Makefile.include
index 312a7e0..7f3a589 100644
--- a/test/openpower-pels/Makefile.include
+++ b/test/openpower-pels/Makefile.include
@@ -11,9 +11,10 @@
 	mru_test \
 	mtms_test \
 	pce_identity_test \
+	pel_manager_test \
+	pel_rules_test \
 	pel_test \
 	pel_values_test \
-	pel_manager_test \
 	private_header_test \
 	real_pel_test \
 	registry_test \
@@ -41,6 +42,7 @@
 	$(top_builddir)/extensions/openpower-pels/mru.o \
 	$(top_builddir)/extensions/openpower-pels/pce_identity.o \
 	$(top_builddir)/extensions/openpower-pels/pel.o \
+	$(top_builddir)/extensions/openpower-pels/pel_rules.o \
 	$(top_builddir)/extensions/openpower-pels/pel_values.o \
 	$(top_builddir)/extensions/openpower-pels/private_header.o \
 	$(top_builddir)/extensions/openpower-pels/registry.o \
@@ -284,3 +286,11 @@
 	$(top_builddir)/extensions/openpower-pels/pce_identity.o \
 	$(top_builddir)/extensions/openpower-pels/src.o
 src_test_LDFLAGS = $(test_ldflags)
+
+pel_rules_test_SOURCES = %reldir%/pel_rules_test.cpp
+pel_rules_test_CPPFLAGS = $(test_cppflags)
+pel_rules_test_CXXFLAGS = $(test_cxxflags)
+pel_rules_test_LDADD = \
+	$(test_ldflags) \
+	$(top_builddir)/extensions/openpower-pels/pel_rules.o
+pel_rules_test_LDFLAGS = $(test_ldflags)
diff --git a/test/openpower-pels/pel_rules_test.cpp b/test/openpower-pels/pel_rules_test.cpp
new file mode 100644
index 0000000..38e5b58
--- /dev/null
+++ b/test/openpower-pels/pel_rules_test.cpp
@@ -0,0 +1,72 @@
+#include "extensions/openpower-pels/pel_rules.hpp"
+
+#include <gtest/gtest.h>
+
+using namespace openpower::pels;
+
+struct CheckParams
+{
+    // pel_rules::check() inputs
+    uint16_t actionFlags;
+    uint8_t eventType;
+    uint8_t severity;
+
+    // pel_rules::check() expected outputs
+    uint16_t expectedActionFlags;
+    uint8_t expectedEventType;
+};
+
+const uint8_t sevInfo = 0x00;
+const uint8_t sevRecovered = 0x10;
+const uint8_t sevPredictive = 0x20;
+const uint8_t sevUnrecov = 0x40;
+const uint8_t sevCrit = 0x50;
+const uint8_t sevDiagnostic = 0x60;
+const uint8_t sevSymptom = 0x70;
+
+const uint8_t typeNA = 0x00;
+const uint8_t typeMisc = 0x01;
+const uint8_t typeTracing = 0x02;
+const uint8_t typeDumpNotif = 0x08;
+
+TEST(PELRulesTest, TestCheckRules)
+{
+    // Impossible to cover all combinations, but
+    // do some interesting ones.
+    std::vector<CheckParams> testParams{
+        // Informational errors w/ empty action flags
+        // and different event types.
+        {0, typeNA, sevInfo, 0x6000, typeMisc},
+        {0, typeMisc, sevInfo, 0x6000, typeMisc},
+        {0, typeTracing, sevInfo, 0x6000, typeTracing},
+        {0, typeDumpNotif, sevInfo, 0x2000, typeDumpNotif},
+
+        // Informational errors with wrong action flags
+        {0x8900, typeNA, sevInfo, 0x6000, typeMisc},
+
+        // Informational errors with extra valid action flags
+        {0x00C0, typeMisc, sevInfo, 0x60C0, typeMisc},
+
+        // Informational - don't report
+        {0x1000, typeMisc, sevInfo, 0x5000, typeMisc},
+
+        // Recovered will report as hidden
+        {0, typeNA, sevRecovered, 0x6000, typeNA},
+
+        // The 5 error severities will have:
+        // service action, report, call home
+        {0, typeNA, sevPredictive, 0xA800, typeNA},
+        {0, typeNA, sevUnrecov, 0xA800, typeNA},
+        {0, typeNA, sevCrit, 0xA800, typeNA},
+        {0, typeNA, sevDiagnostic, 0xA800, typeNA},
+        {0, typeNA, sevSymptom, 0xA800, typeNA}};
+
+    for (const auto& entry : testParams)
+    {
+        auto [actionFlags, type] = pel_rules::check(
+            entry.actionFlags, entry.eventType, entry.severity);
+
+        EXPECT_EQ(actionFlags, entry.expectedActionFlags);
+        EXPECT_EQ(type, entry.expectedEventType);
+    }
+}