1 /**
2  * Copyright © 2019 IBM Corporation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include "extensions/openpower-pels/mru.hpp"
17 
18 #include <gtest/gtest.h>
19 
20 using namespace openpower::pels;
21 using namespace openpower::pels::src;
22 
23 TEST(MRUTest, TestConstructor)
24 {
25     std::vector<uint8_t> data{
26         'M',  'R',  0x28, 0x04, // ID, size, flags
27         0x00, 0x00, 0x00, 0x00, // Reserved
28         0x00, 0x00, 0x00, 'H',  // priority for MRU ID 0
29         0x01, 0x01, 0x01, 0x01, // MRU ID 0
30         0x00, 0x00, 0x00, 'M',  // priority for MRU ID 1
31         0x02, 0x02, 0x02, 0x02, // MRU ID 1
32         0x00, 0x00, 0x00, 'L',  // priority for MRU ID 2
33         0x03, 0x03, 0x03, 0x03, // MRU ID 2
34         0x00, 0x00, 0x00, 'H',  // priority for MRU ID 3
35         0x04, 0x04, 0x04, 0x04, // MRU ID 3
36     };
37 
38     Stream stream{data};
39 
40     MRU mru{stream};
41 
42     EXPECT_EQ(mru.flattenedSize(), data.size());
43     EXPECT_EQ(mru.mrus().size(), 4);
44     EXPECT_EQ(mru.flags(), 4);
45 
46     EXPECT_EQ(mru.mrus().at(0).priority, 'H');
47     EXPECT_EQ(mru.mrus().at(0).id, 0x01010101);
48     EXPECT_EQ(mru.mrus().at(1).priority, 'M');
49     EXPECT_EQ(mru.mrus().at(1).id, 0x02020202);
50     EXPECT_EQ(mru.mrus().at(2).priority, 'L');
51     EXPECT_EQ(mru.mrus().at(2).id, 0x03030303);
52     EXPECT_EQ(mru.mrus().at(3).priority, 'H');
53     EXPECT_EQ(mru.mrus().at(3).id, 0x04040404);
54 
55     // Now flatten
56     std::vector<uint8_t> newData;
57     Stream newStream{newData};
58 
59     mru.flatten(newStream);
60     EXPECT_EQ(data, newData);
61 }
62 
63 TEST(MRUTest, TestBadData)
64 {
65     // 4 MRUs expected, but only 1
66     std::vector<uint8_t> data{
67         'M',  'R',  0x28, 0x04, // ID, size, flags
68         0x00, 0x00, 0x00, 0x00, // Reserved
69         0x00, 0x00, 0x00, 'H',  // priority 0
70         0x01, 0x01, 0x01, 0x01, // MRU ID 0
71     };
72 
73     Stream stream{data};
74     EXPECT_THROW(MRU mru{stream}, std::out_of_range);
75 }
76 
77 TEST(MRUTest, TestVectorConstructor)
78 {
79     {
80         std::vector<MRU::MRUCallout> mrus{{'H', 1}, {'M', 2}, {'L', 3}};
81 
82         MRU mru{mrus};
83 
84         EXPECT_EQ(mru.mrus().size(), 3);
85         EXPECT_EQ(mru.flags(), 3);
86 
87         EXPECT_EQ(mru.mrus().at(0).priority, 'H');
88         EXPECT_EQ(mru.mrus().at(0).id, 1);
89         EXPECT_EQ(mru.mrus().at(1).priority, 'M');
90         EXPECT_EQ(mru.mrus().at(1).id, 2);
91         EXPECT_EQ(mru.mrus().at(2).priority, 'L');
92         EXPECT_EQ(mru.mrus().at(2).id, 3);
93 
94         // Flatten and unflatten
95         std::vector<uint8_t> data;
96         Stream stream{data};
97 
98         mru.flatten(stream);
99         EXPECT_EQ(mru.size(), data.size());
100 
101         stream.offset(0);
102         MRU newMRU{stream};
103 
104         EXPECT_EQ(newMRU.flattenedSize(), data.size());
105         EXPECT_EQ(newMRU.size(), data.size());
106         EXPECT_EQ(newMRU.mrus().size(), 3);
107 
108         EXPECT_EQ(newMRU.mrus().at(0).priority, 'H');
109         EXPECT_EQ(newMRU.mrus().at(0).id, 1);
110         EXPECT_EQ(newMRU.mrus().at(1).priority, 'M');
111         EXPECT_EQ(newMRU.mrus().at(1).id, 2);
112         EXPECT_EQ(newMRU.mrus().at(2).priority, 'L');
113         EXPECT_EQ(newMRU.mrus().at(2).id, 3);
114     }
115 
116     {
117         // Too many MRUs
118         std::vector<MRU::MRUCallout> mrus;
119         for (uint32_t i = 0; i < 20; i++)
120         {
121             MRU::MRUCallout mru = {'H', i};
122             mrus.push_back(mru);
123         }
124 
125         MRU mru{mrus};
126 
127         EXPECT_EQ(mru.mrus().size(), 15);
128         EXPECT_EQ(mru.flags(), 15);
129     }
130 
131     {
132         // Too few MRUs
133         std::vector<MRU::MRUCallout> mrus;
134         EXPECT_THROW(MRU mru{mrus}, std::runtime_error);
135     }
136 }
137