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/callouts.hpp"
17 #include "pel_utils.hpp"
18
19 #include <format>
20
21 #include <gtest/gtest.h>
22
23 using namespace openpower::pels;
24 using namespace openpower::pels::src;
25
TEST(CalloutsTest,UnflattenFlattenTest)26 TEST(CalloutsTest, UnflattenFlattenTest)
27 {
28 std::vector<uint8_t> data{0xC0, 0x00, 0x00,
29 0x00}; // ID, flags, length in words
30
31 // Add 2 callouts
32 auto callout = srcDataFactory(TestSRCType::calloutStructureA);
33 data.insert(data.end(), callout.begin(), callout.end());
34
35 callout = srcDataFactory(TestSRCType::calloutStructureB);
36 data.insert(data.end(), callout.begin(), callout.end());
37
38 Stream stream{data};
39
40 // Set the actual word length value at offset 2
41 uint16_t wordLength = data.size() / 4;
42 stream.offset(2);
43 stream << wordLength;
44 stream.offset(0);
45
46 Callouts callouts{stream};
47
48 EXPECT_EQ(callouts.flattenedSize(), data.size());
49 EXPECT_EQ(callouts.callouts().size(), 2);
50
51 // spot check that each callout has the right substructures
52 EXPECT_TRUE(callouts.callouts().front()->fruIdentity());
53 EXPECT_FALSE(callouts.callouts().front()->pceIdentity());
54 EXPECT_FALSE(callouts.callouts().front()->mru());
55
56 EXPECT_TRUE(callouts.callouts().back()->fruIdentity());
57 EXPECT_TRUE(callouts.callouts().back()->pceIdentity());
58 EXPECT_TRUE(callouts.callouts().back()->mru());
59
60 // Flatten
61 std::vector<uint8_t> newData;
62 Stream newStream{newData};
63
64 callouts.flatten(newStream);
65 EXPECT_EQ(data, newData);
66 }
67
TEST(CalloutsTest,BadDataTest)68 TEST(CalloutsTest, BadDataTest)
69 {
70 // Start out with a valid 2 callout object, then truncate it.
71 std::vector<uint8_t> data{0xC0, 0x00, 0x00,
72 0x00}; // ID, flags, length in words
73
74 // Add 2 callouts
75 auto callout = srcDataFactory(TestSRCType::calloutStructureA);
76 data.insert(data.end(), callout.begin(), callout.end());
77
78 callout = srcDataFactory(TestSRCType::calloutStructureB);
79 data.insert(data.end(), callout.begin(), callout.end());
80
81 Stream stream{data};
82
83 // Set the actual word length value at offset 2
84 uint16_t wordLength = data.size() / 4;
85 stream.offset(2);
86 stream << wordLength;
87 stream.offset(0);
88
89 // Shorten the data by an arbitrary amount so unflattening goes awry.
90 data.resize(data.size() - 37);
91
92 EXPECT_THROW(Callouts callouts{stream}, std::out_of_range);
93 }
94
TEST(CalloutsTest,TestAddCallouts)95 TEST(CalloutsTest, TestAddCallouts)
96 {
97 Callouts callouts;
98
99 // Empty Callouts size
100 size_t lastSize = 4;
101
102 for (size_t i = 0; i < maxNumberOfCallouts; i++)
103 {
104 auto loc = std::format("U1-P{}", i);
105 auto callout = std::make_unique<Callout>(
106 CalloutPriority::high, loc, "1234567", "ABCD", "123456789ABC");
107 auto calloutSize = callout->flattenedSize();
108
109 callouts.addCallout(std::move(callout));
110
111 EXPECT_EQ(callouts.flattenedSize(), lastSize + calloutSize);
112
113 lastSize = callouts.flattenedSize();
114
115 EXPECT_EQ(callouts.callouts().size(), i + 1);
116 }
117
118 // Try to add an 11th callout. Shouldn't work
119
120 auto callout = std::make_unique<Callout>(CalloutPriority::high, "U1-P1",
121 "1234567", "ABCD", "123456789ABC");
122 callouts.addCallout(std::move(callout));
123
124 EXPECT_EQ(callouts.callouts().size(), maxNumberOfCallouts);
125 }
126
TEST(CalloutsTest,TestSortCallouts)127 TEST(CalloutsTest, TestSortCallouts)
128 {
129 Callouts callouts;
130
131 // Add callouts with different priorities to test sorting in descending
132 // order
133
134 auto c0 = std::make_unique<Callout>(CalloutPriority::high, "U1-P1",
135 "1234567", "ABC", "123456789ABC");
136
137 callouts.addCallout(std::move(c0));
138
139 auto c1 = std::make_unique<Callout>(CalloutPriority::medium, "U1-P2",
140 "1234567", "ABCD", "123456789ABC");
141
142 callouts.addCallout(std::move(c1));
143
144 auto c2 = std::make_unique<Callout>(CalloutPriority::low, "U1-P3",
145 "1234567", "ABCDE", "123456789ABC");
146
147 callouts.addCallout(std::move(c2));
148
149 auto c3 = std::make_unique<Callout>(CalloutPriority::high, "U1-P4",
150 "1234567", "ABCDE1", "123456789ABC");
151
152 callouts.addCallout(std::move(c3));
153
154 auto c4 = std::make_unique<Callout>(CalloutPriority::high, "U1-P5",
155 "1234567", "ABCDE2", "123456789ABC");
156
157 callouts.addCallout(std::move(c4));
158
159 auto c5 = std::make_unique<Callout>(CalloutPriority::low, "U1-P6",
160 "1234567", "ABCDE2", "123456789ABC");
161
162 callouts.addCallout(std::move(c5));
163
164 auto c6 = std::make_unique<Callout>(CalloutPriority::medium, "U1-P7",
165 "1234567", "ABCD2", "123456789ABC");
166
167 callouts.addCallout(std::move(c6));
168
169 auto c7 = std::make_unique<Callout>(CalloutPriority::mediumGroupA, "U1-P8",
170 "1234567", "ABCDE3", "123456789ABC");
171
172 callouts.addCallout(std::move(c7));
173
174 auto c8 = std::make_unique<Callout>(CalloutPriority::mediumGroupC, "U1-P9",
175 "1234567", "ABCDE4", "123456789ABC");
176
177 callouts.addCallout(std::move(c8));
178
179 auto c9 = std::make_unique<Callout>(CalloutPriority::low, "U1-P10",
180 "1234567", "ABCDE3", "123456789ABC");
181
182 callouts.addCallout(std::move(c9));
183
184 const auto& calloutObjects = callouts.callouts();
185 EXPECT_EQ(calloutObjects[0]->locationCode(), "U1-P1");
186 EXPECT_EQ(calloutObjects[0]->priority(), 'H');
187 EXPECT_EQ(calloutObjects[1]->locationCode(), "U1-P4");
188 EXPECT_EQ(calloutObjects[1]->priority(), 'H');
189 EXPECT_EQ(calloutObjects[2]->locationCode(), "U1-P5");
190 EXPECT_EQ(calloutObjects[2]->priority(), 'H');
191 EXPECT_EQ(calloutObjects[3]->locationCode(), "U1-P2");
192 EXPECT_EQ(calloutObjects[3]->priority(), 'M');
193 EXPECT_EQ(calloutObjects[4]->locationCode(), "U1-P7");
194 EXPECT_EQ(calloutObjects[4]->priority(), 'M');
195 EXPECT_EQ(calloutObjects[5]->locationCode(), "U1-P8");
196 EXPECT_EQ(calloutObjects[5]->priority(), 'A');
197 EXPECT_EQ(calloutObjects[6]->locationCode(), "U1-P9");
198 EXPECT_EQ(calloutObjects[6]->priority(), 'C');
199 EXPECT_EQ(calloutObjects[7]->locationCode(), "U1-P3");
200 EXPECT_EQ(calloutObjects[7]->priority(), 'L');
201 EXPECT_EQ(calloutObjects[8]->locationCode(), "U1-P6");
202 EXPECT_EQ(calloutObjects[8]->priority(), 'L');
203 EXPECT_EQ(calloutObjects[9]->locationCode(), "U1-P10");
204 EXPECT_EQ(calloutObjects[9]->priority(), 'L');
205 }
206
TEST(CalloutsTest,TestDupCallouts)207 TEST(CalloutsTest, TestDupCallouts)
208 {
209 {
210 // Duplicate callouts, keep the high priority one
211 Callouts callouts;
212 auto c0 = std::make_unique<Callout>(CalloutPriority::medium, "U1-P1",
213 "1234567", "ABC", "123456789ABC");
214 callouts.addCallout(std::move(c0));
215
216 auto c1 = std::make_unique<Callout>(CalloutPriority::high, "U1-P1",
217 "1234567", "ABCD", "123456789ABC");
218 callouts.addCallout(std::move(c1));
219
220 EXPECT_EQ(callouts.callouts().size(), 1);
221 const auto& calloutObjects = callouts.callouts();
222 EXPECT_EQ(calloutObjects[0]->priority(), 'H');
223 }
224
225 {
226 // Different callouts, keep them both
227 Callouts callouts;
228 auto c0 = std::make_unique<Callout>(CalloutPriority::high, "U1-P1",
229 "1234567", "ABC", "123456789ABC");
230 callouts.addCallout(std::move(c0));
231
232 auto c1 = std::make_unique<Callout>(CalloutPriority::medium, "U1-P2",
233 "1234567", "ABCD", "123456789ABC");
234 callouts.addCallout(std::move(c1));
235
236 EXPECT_EQ(callouts.callouts().size(), 2);
237 }
238
239 {
240 // Two duplicates and two unique. Needs sorting.
241 Callouts callouts;
242 auto c0 = std::make_unique<Callout>(CalloutPriority::low, "U1-P9",
243 "1234567", "ABCD", "123456789ABC");
244 callouts.addCallout(std::move(c0));
245
246 auto c1 = std::make_unique<Callout>(CalloutPriority::low, "U1-P1",
247 "1234567", "ABC", "123456789ABC");
248 callouts.addCallout(std::move(c1));
249
250 auto c2 = std::make_unique<Callout>(CalloutPriority::high, "U1-P1",
251 "1234567", "ABC", "123456789ABC");
252 callouts.addCallout(std::move(c2));
253
254 auto c3 = std::make_unique<Callout>(CalloutPriority::medium, "U1-P5",
255 "1234567", "ABCD", "123456789ABC");
256 callouts.addCallout(std::move(c3));
257
258 const auto& calloutObjects = callouts.callouts();
259 EXPECT_EQ(callouts.callouts().size(), 3);
260 EXPECT_EQ(calloutObjects[0]->priority(), 'H');
261 EXPECT_EQ(calloutObjects[0]->locationCode(), "U1-P1");
262 EXPECT_EQ(calloutObjects[1]->priority(), 'M');
263 EXPECT_EQ(calloutObjects[1]->locationCode(), "U1-P5");
264 EXPECT_EQ(calloutObjects[2]->priority(), 'L');
265 EXPECT_EQ(calloutObjects[2]->locationCode(), "U1-P9");
266 }
267 }
268