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