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 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 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 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 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 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