PEL: Let Callout object ctor take a MRU list

A list of MRUs (Manufacturing Replaceable Units) can now be passed into
the Callout object constructor.  There is also a new MRU object
constructor that will build that object with a MRU list as well.

This will be used in the future when someone wants to add MRUs to a
callout.

Signed-off-by: Matt Spinler <spinler@us.ibm.com>
Change-Id: Ic0e93e081a91ffc47dfd6642a34f02fd9a6edb8e
diff --git a/test/openpower-pels/mru_test.cpp b/test/openpower-pels/mru_test.cpp
index e73c69a..d6b3eb6 100644
--- a/test/openpower-pels/mru_test.cpp
+++ b/test/openpower-pels/mru_test.cpp
@@ -41,6 +41,7 @@
 
     EXPECT_EQ(mru.flattenedSize(), data.size());
     EXPECT_EQ(mru.mrus().size(), 4);
+    EXPECT_EQ(mru.flags(), 4);
 
     EXPECT_EQ(mru.mrus().at(0).priority, 'H');
     EXPECT_EQ(mru.mrus().at(0).id, 0x01010101);
@@ -72,3 +73,64 @@
     Stream stream{data};
     EXPECT_THROW(MRU mru{stream}, std::out_of_range);
 }
+
+TEST(MRUTest, TestVectorConstructor)
+{
+    {
+        std::vector<MRU::MRUCallout> mrus{{'H', 1}, {'M', 2}, {'L', 3}};
+
+        MRU mru{mrus};
+
+        EXPECT_EQ(mru.mrus().size(), 3);
+        EXPECT_EQ(mru.flags(), 3);
+
+        EXPECT_EQ(mru.mrus().at(0).priority, 'H');
+        EXPECT_EQ(mru.mrus().at(0).id, 1);
+        EXPECT_EQ(mru.mrus().at(1).priority, 'M');
+        EXPECT_EQ(mru.mrus().at(1).id, 2);
+        EXPECT_EQ(mru.mrus().at(2).priority, 'L');
+        EXPECT_EQ(mru.mrus().at(2).id, 3);
+
+        // Flatten and unflatten
+        std::vector<uint8_t> data;
+        Stream stream{data};
+
+        mru.flatten(stream);
+        EXPECT_EQ(mru.size(), data.size());
+
+        stream.offset(0);
+        MRU newMRU{stream};
+
+        EXPECT_EQ(newMRU.flattenedSize(), data.size());
+        EXPECT_EQ(newMRU.size(), data.size());
+        EXPECT_EQ(newMRU.mrus().size(), 3);
+
+        EXPECT_EQ(newMRU.mrus().at(0).priority, 'H');
+        EXPECT_EQ(newMRU.mrus().at(0).id, 1);
+        EXPECT_EQ(newMRU.mrus().at(1).priority, 'M');
+        EXPECT_EQ(newMRU.mrus().at(1).id, 2);
+        EXPECT_EQ(newMRU.mrus().at(2).priority, 'L');
+        EXPECT_EQ(newMRU.mrus().at(2).id, 3);
+    }
+
+    {
+        // Too many MRUs
+        std::vector<MRU::MRUCallout> mrus;
+        for (uint32_t i = 0; i < 20; i++)
+        {
+            MRU::MRUCallout mru = {'H', i};
+            mrus.push_back(mru);
+        }
+
+        MRU mru{mrus};
+
+        EXPECT_EQ(mru.mrus().size(), 15);
+        EXPECT_EQ(mru.flags(), 15);
+    }
+
+    {
+        // Too few MRUs
+        std::vector<MRU::MRUCallout> mrus;
+        EXPECT_THROW(MRU mru{mrus}, std::runtime_error);
+    }
+}
diff --git a/test/openpower-pels/src_callout_test.cpp b/test/openpower-pels/src_callout_test.cpp
index fa93111..12f8c2b 100644
--- a/test/openpower-pels/src_callout_test.cpp
+++ b/test/openpower-pels/src_callout_test.cpp
@@ -276,6 +276,34 @@
             EXPECT_EQ(fru->getSN().value(), "123456789ABC");
         }
     }
+
+    {
+        // With MRUs
+        std::vector<MRU::MRUCallout> mruList{{'H', 1}, {'H', 2}};
+
+        Callout callout{CalloutPriority::high, "U99-P5", "1234567", "ABCD",
+                        "123456789ABC",        mruList};
+
+        EXPECT_EQ(callout.flags(), Callout::calloutType |
+                                       Callout::fruIdentIncluded |
+                                       Callout::mruIncluded);
+
+        EXPECT_EQ(callout.priority(), 'H');
+        EXPECT_EQ(callout.locationCode(), "U99-P5");
+        EXPECT_EQ(callout.locationCodeSize(), 8);
+
+        auto& fru = callout.fruIdentity();
+        EXPECT_EQ(fru->getPN().value(), "1234567");
+        EXPECT_EQ(fru->getCCIN().value(), "ABCD");
+        EXPECT_EQ(fru->getSN().value(), "123456789ABC");
+
+        auto& mruSection = callout.mru();
+        EXPECT_EQ(mruSection->mrus().size(), 2);
+        EXPECT_EQ(mruSection->mrus().at(0).priority, 'H');
+        EXPECT_EQ(mruSection->mrus().at(0).id, 1);
+        EXPECT_EQ(mruSection->mrus().at(1).priority, 'H');
+        EXPECT_EQ(mruSection->mrus().at(1).id, 2);
+    }
 }
 
 // Create a callout object by passing in the maintenance procedure to add.