blob: 4bc3282255cdc9159cbcdd6f2ca10224fb59c723 [file] [log] [blame]
Matt Spinler97f7abc2019-11-06 09:40:23 -06001/**
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 */
Matt Spinler89fa0822019-07-17 13:54:30 -050016#include "extensions/openpower-pels/paths.hpp"
17#include "extensions/openpower-pels/repository.hpp"
18#include "pel_utils.hpp"
19
20#include <ext/stdio_filebuf.h>
21
22#include <filesystem>
23
24#include <gtest/gtest.h>
25
26using namespace openpower::pels;
27namespace fs = std::filesystem;
28
29/**
30 * Clean the Repo after every testcase.
31 * And because we have PEL object, also clean up
32 * the log ID.
33 */
34class RepositoryTest : public CleanLogID
35{
36 protected:
37 void SetUp() override
38 {
39 repoPath = getPELRepoPath();
40 }
41
42 void TearDown() override
43 {
44 fs::remove_all(repoPath);
45 }
46
47 fs::path repoPath;
48};
49
50TEST_F(RepositoryTest, FilenameTest)
51{
52 BCDTime date = {0x20, 0x30, 0x11, 0x28, 0x13, 0x6, 0x7, 0x8};
53
54 EXPECT_EQ(Repository::getPELFilename(0x12345678, date),
55 "2030112813060708_12345678");
56
57 EXPECT_EQ(Repository::getPELFilename(0xAABBCCDD, date),
58 "2030112813060708_AABBCCDD");
59
60 EXPECT_EQ(Repository::getPELFilename(0x3AFF1, date),
61 "2030112813060708_0003AFF1");
62
63 EXPECT_EQ(Repository::getPELFilename(100, date),
64 "2030112813060708_00000064");
65
66 EXPECT_EQ(Repository::getPELFilename(0, date), "2030112813060708_00000000");
67}
68
69TEST_F(RepositoryTest, AddTest)
70{
71 Repository repo{repoPath};
Matt Spinler42828bd2019-10-11 10:39:30 -050072 auto data = pelDataFactory(TestPELType::pelSimple);
73 auto pel = std::make_unique<PEL>(data);
Matt Spinler89fa0822019-07-17 13:54:30 -050074
75 repo.add(pel);
76
77 // Check that the PEL was stored where it was supposed to be,
78 // and that it wrote the PEL data.
Matt Spinler97d19b42019-10-29 11:34:03 -050079 const auto ts = pel->privateHeader().commitTimestamp();
Matt Spinler89fa0822019-07-17 13:54:30 -050080 auto name = Repository::getPELFilename(pel->id(), ts);
81
82 fs::path file = repoPath / "logs" / name;
83 EXPECT_TRUE(fs::exists(file));
84
85 auto newData = readPELFile(file);
86 auto pelData = pel->data();
87 EXPECT_EQ(*newData, pelData);
88}
Matt Spinler475e5742019-07-18 16:09:49 -050089
Matt Spinler52602e32020-07-15 12:37:28 -050090TEST_F(RepositoryTest, RemoveTest)
91{
92 using pelID = Repository::LogID::Pel;
93 using obmcID = Repository::LogID::Obmc;
94
95 // Add and remove a PEL from the repo
96
97 Repository repo{repoPath};
98
99 auto data = pelDataFactory(TestPELType::pelSimple);
100 auto pel = std::make_unique<PEL>(data, 1);
101
102 pel->assignID();
103 Repository::LogID id{pelID{pel->id()}, obmcID{pel->obmcLogID()}};
104
105 repo.add(pel);
106
107 auto removedID = repo.remove(id);
108 ASSERT_TRUE(removedID);
109 EXPECT_EQ(*removedID, id);
110
111 EXPECT_FALSE(repo.hasPEL(id));
112
113 // Try to remove it again, not there
114 EXPECT_FALSE(repo.remove(id));
115}
116
Matt Spinler475e5742019-07-18 16:09:49 -0500117TEST_F(RepositoryTest, RestoreTest)
118{
119 using pelID = Repository::LogID::Pel;
120 using obmcID = Repository::LogID::Obmc;
121
122 std::vector<Repository::LogID> ids;
123
124 {
125 Repository repo{repoPath};
126
127 // Add some PELs to the repository
128 {
Matt Spinler42828bd2019-10-11 10:39:30 -0500129 auto data = pelDataFactory(TestPELType::pelSimple);
130 auto pel = std::make_unique<PEL>(data, 1);
Matt Spinler475e5742019-07-18 16:09:49 -0500131 pel->assignID();
132 repo.add(pel);
133 ids.emplace_back(pelID(pel->id()), obmcID(1));
134 }
135 {
Matt Spinler42828bd2019-10-11 10:39:30 -0500136 auto data = pelDataFactory(TestPELType::pelSimple);
137 auto pel = std::make_unique<PEL>(data, 2);
Matt Spinler475e5742019-07-18 16:09:49 -0500138 pel->assignID();
139 repo.add(pel);
140 ids.emplace_back(pelID(pel->id()), obmcID(2));
141 }
142
143 // Check they're there
144 EXPECT_TRUE(repo.hasPEL(ids[0]));
145 EXPECT_TRUE(repo.hasPEL(ids[1]));
146
147 // Do some other search tests while we're here.
148
149 // Search based on PEL ID
150 Repository::LogID id(pelID(ids[0].pelID));
151 EXPECT_TRUE(repo.hasPEL(id));
152
153 // Search based on OBMC log ID
154 id.pelID.id = 0;
155 id.obmcID = ids[0].obmcID;
156 EXPECT_TRUE(repo.hasPEL(id));
157
158 // ... based on the other PEL ID
159 id.pelID = ids[1].pelID;
160 id.obmcID.id = 0;
161 EXPECT_TRUE(repo.hasPEL(id));
162
163 // Not found
164 id.pelID.id = 99;
165 id.obmcID.id = 100;
166 EXPECT_FALSE(repo.hasPEL(id));
Matt Spinler52602e32020-07-15 12:37:28 -0500167
168 // Try to remove it anyway
169 EXPECT_FALSE(repo.remove(id));
Matt Spinler475e5742019-07-18 16:09:49 -0500170 }
171
172 {
173 // Restore and check they're still there, then
174 // remove them.
175 Repository repo{repoPath};
176 EXPECT_TRUE(repo.hasPEL(ids[0]));
177 EXPECT_TRUE(repo.hasPEL(ids[1]));
178
179 repo.remove(ids[0]);
180 EXPECT_FALSE(repo.hasPEL(ids[0]));
181
182 repo.remove(ids[1]);
183 EXPECT_FALSE(repo.hasPEL(ids[1]));
184 }
185}
Matt Spinler2813f362019-07-19 12:45:28 -0500186
187TEST_F(RepositoryTest, TestGetPELData)
188{
189 using ID = Repository::LogID;
190 Repository repo{repoPath};
191
192 ID badID{ID::Pel(42)};
193 auto noData = repo.getPELData(badID);
194 EXPECT_FALSE(noData);
195
196 // Add a PEL to the repo, and get the data back with getPELData.
Matt Spinler42828bd2019-10-11 10:39:30 -0500197 auto data = pelDataFactory(TestPELType::pelSimple);
198 auto dataCopy = data;
199 auto pel = std::make_unique<PEL>(data);
Matt Spinler2813f362019-07-19 12:45:28 -0500200 auto pelID = pel->id();
201 repo.add(pel);
202
203 ID id{ID::Pel(pelID)};
204 auto pelData = repo.getPELData(id);
205
206 ASSERT_TRUE(pelData);
207 EXPECT_EQ(dataCopy, *pelData);
208}
Matt Spinler1ea78802019-11-01 13:04:59 -0500209
210TEST_F(RepositoryTest, TestForEach)
211{
212 Repository repo{repoPath};
213
214 // Add 2 PELs
215 auto data = pelDataFactory(TestPELType::pelSimple);
216 auto pel = std::make_unique<PEL>(data);
217 repo.add(pel);
218
219 pel = std::make_unique<PEL>(data);
220 pel->assignID();
221 pel->setCommitTime();
222 repo.add(pel);
223
224 // Make a function that saves the IDs
225 std::vector<uint32_t> ids;
226 Repository::ForEachFunc f1 = [&ids](const PEL& pel) {
227 ids.push_back(pel.id());
228 return false;
229 };
230
231 repo.for_each(f1);
232
233 EXPECT_EQ(ids.size(), 2);
234
235 // Stop after the first time in.
236 Repository::ForEachFunc f2 = [&ids](const PEL& pel) {
237 ids.push_back(pel.id());
238 return true;
239 };
240
241 ids.clear();
242 repo.for_each(f2);
243 EXPECT_EQ(ids.size(), 1);
244}
Matt Spinler421f6532019-11-06 15:40:45 -0600245
246TEST_F(RepositoryTest, TestSubscriptions)
247{
248 std::vector<uint32_t> added;
249 std::vector<uint32_t> removed;
250
251 Repository::AddCallback ac = [&added](const PEL& pel) {
252 added.push_back(pel.id());
253 };
254
255 Repository::DeleteCallback dc = [&removed](uint32_t id) {
256 removed.push_back(id);
257 };
258
259 Repository repo{repoPath};
260 repo.subscribeToAdds("test", ac);
261 repo.subscribeToDeletes("test", dc);
262
263 auto data = pelDataFactory(TestPELType::pelSimple);
264 auto pel = std::make_unique<PEL>(data);
265 auto pelID = pel->id();
266 repo.add(pel);
267
268 EXPECT_EQ(added.size(), 1);
269
270 using ID = Repository::LogID;
271 ID id{ID::Pel(pelID)};
272 repo.remove(id);
273
274 EXPECT_EQ(removed.size(), 1);
275
276 repo.unsubscribeFromAdds("test");
277 repo.unsubscribeFromDeletes("test");
278
279 added.clear();
280 removed.clear();
281
282 repo.add(pel);
283 EXPECT_EQ(added.size(), 0);
284
285 repo.remove(id);
286 EXPECT_EQ(removed.size(), 0);
287}
Matt Spinler0ff00482019-11-06 16:19:46 -0600288
289TEST_F(RepositoryTest, TestGetAttributes)
290{
291 uint32_t pelID = 0;
292 std::bitset<16> actionFlags;
293
294 {
295 Repository repo{repoPath};
296
297 // Add a PEL to the repo
298 auto data = pelDataFactory(TestPELType::pelSimple);
299 auto pel = std::make_unique<PEL>(data);
300 repo.add(pel);
301
302 pelID = pel->id();
303 actionFlags = pel->userHeader().actionFlags();
304
305 using ID = Repository::LogID;
306 ID id{ID::Pel(pelID)};
307
308 auto a = repo.getPELAttributes(id);
309 EXPECT_TRUE(a);
310 EXPECT_EQ((*a).get().actionFlags, actionFlags);
311
312 id.pelID.id = 0;
313 a = repo.getPELAttributes(id);
314 EXPECT_FALSE(a);
315 }
316
317 {
318 // Restore the repository and check again
319 Repository repo{repoPath};
320
321 using ID = Repository::LogID;
322 ID id{ID::Pel(pelID)};
323
324 auto a = repo.getPELAttributes(id);
325 EXPECT_TRUE(a);
326 EXPECT_EQ((*a).get().actionFlags, actionFlags);
327
328 id.pelID.id = 0;
329 a = repo.getPELAttributes(id);
330 EXPECT_FALSE(a);
331 }
332}
Matt Spinler29d18c12019-11-21 13:31:27 -0600333
334TEST_F(RepositoryTest, TestSetHostState)
335{
336 // Add a PEL to the repo
337 auto data = pelDataFactory(TestPELType::pelSimple);
338 auto pel = std::make_unique<PEL>(data);
339 using ID = Repository::LogID;
340 ID id{ID::Pel(pel->id())};
341
342 {
343 Repository repo{repoPath};
344
345 repo.add(pel);
346
347 auto a = repo.getPELAttributes(id);
348 EXPECT_EQ((*a).get().hostState, TransmissionState::newPEL);
349
350 repo.setPELHostTransState(pel->id(), TransmissionState::acked);
351
352 // First, check the attributes
353 a = repo.getPELAttributes(id);
354 EXPECT_EQ((*a).get().hostState, TransmissionState::acked);
355
356 // Next, check the PEL data itself
357 auto pelData = repo.getPELData(id);
358 PEL newPEL{*pelData};
359 EXPECT_EQ(newPEL.hostTransmissionState(), TransmissionState::acked);
360 }
361
362 {
363 // Now restore, and check again
364 Repository repo{repoPath};
365
366 // First, check the attributes
367 auto a = repo.getPELAttributes(id);
368 EXPECT_EQ((*a).get().hostState, TransmissionState::acked);
369
370 // Next, check the PEL data itself
371 auto pelData = repo.getPELData(id);
372 PEL newPEL{*pelData};
373 EXPECT_EQ(newPEL.hostTransmissionState(), TransmissionState::acked);
374 }
375}
376
377TEST_F(RepositoryTest, TestSetHMCState)
378{
379 // Add a PEL to the repo
380 auto data = pelDataFactory(TestPELType::pelSimple);
381 auto pel = std::make_unique<PEL>(data);
382 using ID = Repository::LogID;
383 ID id{ID::Pel(pel->id())};
384
385 {
386 Repository repo{repoPath};
387
388 repo.add(pel);
389
390 auto a = repo.getPELAttributes(id);
391 EXPECT_EQ((*a).get().hmcState, TransmissionState::newPEL);
392
393 repo.setPELHMCTransState(pel->id(), TransmissionState::acked);
394
395 // First, check the attributes
396 a = repo.getPELAttributes(id);
397 EXPECT_EQ((*a).get().hmcState, TransmissionState::acked);
398
399 // Next, check the PEL data itself
400 auto pelData = repo.getPELData(id);
401 PEL newPEL{*pelData};
402 EXPECT_EQ(newPEL.hmcTransmissionState(), TransmissionState::acked);
403 }
404
405 {
406 // Now restore, and check again
407 Repository repo{repoPath};
408
409 // First, check the attributes
410 auto a = repo.getPELAttributes(id);
411 EXPECT_EQ((*a).get().hmcState, TransmissionState::acked);
412
413 // Next, check the PEL data itself
414 auto pelData = repo.getPELData(id);
415 PEL newPEL{*pelData};
416 EXPECT_EQ(newPEL.hmcTransmissionState(), TransmissionState::acked);
417 }
418}
Matt Spinler6d512242019-12-09 13:44:17 -0600419
420TEST_F(RepositoryTest, TestGetPELFD)
421{
422 Repository repo{repoPath};
423
424 auto data = pelDataFactory(TestPELType::pelSimple);
425 auto pel = std::make_unique<PEL>(data);
426 pel->setCommitTime();
427 pel->assignID();
428
429 repo.add(pel);
430
431 using ID = Repository::LogID;
432 ID id{ID::Pel(pel->id())};
433
434 auto fd = repo.getPELFD(id);
435
436 EXPECT_TRUE(fd);
437
438 // Get the size
439 struct stat s;
440 int r = fstat(*fd, &s);
441 ASSERT_EQ(r, 0);
442
443 auto size = s.st_size;
444
445 // Read the PEL data out of the FD
446 FILE* fp = fdopen(*fd, "r");
447 ASSERT_NE(fp, nullptr);
448
449 std::vector<uint8_t> newData;
450 newData.resize(size);
451 r = fread(newData.data(), 1, size, fp);
452 EXPECT_EQ(r, size);
453
454 PEL newPEL{newData};
455
456 EXPECT_TRUE(newPEL.valid());
457 EXPECT_EQ(newPEL.id(), pel->id());
458
459 fclose(fp);
460
461 // Call getPELFD again, this time with a bad ID
462 id.pelID.id = 42;
463 fd = repo.getPELFD(id);
464
465 EXPECT_FALSE(fd);
466}
Matt Spinlerb188f782020-07-07 11:18:12 -0500467
468// Test the repo size statistics
469TEST_F(RepositoryTest, TestRepoSizes)
470{
471 uint32_t id = 1;
472
473 Repository repo{repoPath, 10000, 500};
474
475 // All of the size stats are the sizes on disk a PEL takes up,
476 // which is different than the file size. Disk usage seems
477 // to have a granularity of 4096 bytes. This probably shouldn't
478 // be hardcoded, but I don't know how to look it up dynamically.
479
480 // All sizes are zero
481 {
482 const auto& stats = repo.getSizeStats();
483 EXPECT_EQ(stats.total, 0);
484 EXPECT_EQ(stats.bmc, 0);
485 EXPECT_EQ(stats.nonBMC, 0);
486 EXPECT_EQ(stats.bmcServiceable, 0);
487 EXPECT_EQ(stats.bmcInfo, 0);
488 EXPECT_EQ(stats.nonBMCServiceable, 0);
489 EXPECT_EQ(stats.nonBMCInfo, 0);
490 }
491
492 // Add a 2000B BMC predictive error
493 auto data = pelFactory(id++, 'O', 0x20, 0x8800, 2000);
494 auto pel = std::make_unique<PEL>(data);
495 auto pelID1 = pel->id();
496 repo.add(pel);
497
498 {
499 const auto& stats = repo.getSizeStats();
500 EXPECT_EQ(stats.total, 4096);
501 EXPECT_EQ(stats.bmc, 4096);
502 EXPECT_EQ(stats.nonBMC, 0);
503 EXPECT_EQ(stats.bmcServiceable, 4096);
504 EXPECT_EQ(stats.bmcInfo, 0);
505 EXPECT_EQ(stats.nonBMCServiceable, 0);
506 EXPECT_EQ(stats.nonBMCInfo, 0);
507 }
508
509 // Add a 5000B BMC informational error
510 data = pelFactory(id++, 'O', 0x00, 0x8800, 5000);
511 pel = std::make_unique<PEL>(data);
512 auto pelID2 = pel->id();
513 repo.add(pel);
514
515 {
516 const auto& stats = repo.getSizeStats();
517 EXPECT_EQ(stats.total, 4096 + 8192);
518 EXPECT_EQ(stats.bmc, 4096 + 8192);
519 EXPECT_EQ(stats.nonBMC, 0);
520 EXPECT_EQ(stats.bmcServiceable, 4096);
521 EXPECT_EQ(stats.bmcInfo, 8192);
522 EXPECT_EQ(stats.nonBMCServiceable, 0);
523 EXPECT_EQ(stats.nonBMCInfo, 0);
524 }
525
526 // Add a 4000B Hostboot unrecoverable error
527 data = pelFactory(id++, 'B', 0x40, 0x8800, 4000);
528 pel = std::make_unique<PEL>(data);
529 auto pelID3 = pel->id();
530 repo.add(pel);
531
532 {
533 const auto& stats = repo.getSizeStats();
534 EXPECT_EQ(stats.total, 4096 + 8192 + 4096);
535 EXPECT_EQ(stats.bmc, 4096 + 8192);
536 EXPECT_EQ(stats.nonBMC, 4096);
537 EXPECT_EQ(stats.bmcServiceable, 4096);
538 EXPECT_EQ(stats.bmcInfo, 8192);
539 EXPECT_EQ(stats.nonBMCServiceable, 4096);
540 EXPECT_EQ(stats.nonBMCInfo, 0);
541 }
542
543 // Add a 5000B Hostboot informational error
544 data = pelFactory(id++, 'B', 0x00, 0x8800, 5000);
545 pel = std::make_unique<PEL>(data);
546 auto pelID4 = pel->id();
547 repo.add(pel);
548
549 {
550 const auto& stats = repo.getSizeStats();
551 EXPECT_EQ(stats.total, 4096 + 8192 + 4096 + 8192);
552 EXPECT_EQ(stats.bmc, 4096 + 8192);
553 EXPECT_EQ(stats.nonBMC, 4096 + 8192);
554 EXPECT_EQ(stats.bmcServiceable, 4096);
555 EXPECT_EQ(stats.bmcInfo, 8192);
556 EXPECT_EQ(stats.nonBMCServiceable, 4096);
557 EXPECT_EQ(stats.nonBMCInfo, 8192);
558 }
559
560 // Remove the BMC serviceable error
561 using ID = Repository::LogID;
562 ID id1{ID::Pel(pelID1)};
563
564 repo.remove(id1);
565 {
566 const auto& stats = repo.getSizeStats();
567 EXPECT_EQ(stats.total, 8192 + 4096 + 8192);
568 EXPECT_EQ(stats.bmc, 8192);
569 EXPECT_EQ(stats.nonBMC, 4096 + 8192);
570 EXPECT_EQ(stats.bmcServiceable, 0);
571 EXPECT_EQ(stats.bmcInfo, 8192);
572 EXPECT_EQ(stats.nonBMCServiceable, 4096);
573 EXPECT_EQ(stats.nonBMCInfo, 8192);
574 }
575
576 // Remove the Hostboot informational error
577 ID id4{ID::Pel(pelID4)};
578
579 repo.remove(id4);
580 {
581 const auto& stats = repo.getSizeStats();
582 EXPECT_EQ(stats.total, 8192 + 4096);
583 EXPECT_EQ(stats.bmc, 8192);
584 EXPECT_EQ(stats.nonBMC, 4096);
585 EXPECT_EQ(stats.bmcServiceable, 0);
586 EXPECT_EQ(stats.bmcInfo, 8192);
587 EXPECT_EQ(stats.nonBMCServiceable, 4096);
588 EXPECT_EQ(stats.nonBMCInfo, 0);
589 }
590
591 // Remove the BMC informational error
592 ID id2{ID::Pel(pelID2)};
593
594 repo.remove(id2);
595 {
596 const auto& stats = repo.getSizeStats();
597 EXPECT_EQ(stats.total, 4096);
598 EXPECT_EQ(stats.bmc, 0);
599 EXPECT_EQ(stats.nonBMC, 4096);
600 EXPECT_EQ(stats.bmcServiceable, 0);
601 EXPECT_EQ(stats.bmcInfo, 0);
602 EXPECT_EQ(stats.nonBMCServiceable, 4096);
603 EXPECT_EQ(stats.nonBMCInfo, 0);
604 }
605
606 // Remove the hostboot unrecoverable error
607 ID id3{ID::Pel(pelID3)};
608
609 repo.remove(id3);
610 {
611 const auto& stats = repo.getSizeStats();
612 EXPECT_EQ(stats.total, 0);
613 EXPECT_EQ(stats.bmc, 0);
614 EXPECT_EQ(stats.nonBMC, 0);
615 EXPECT_EQ(stats.bmcServiceable, 0);
616 EXPECT_EQ(stats.bmcInfo, 0);
617 EXPECT_EQ(stats.nonBMCServiceable, 0);
618 EXPECT_EQ(stats.nonBMCInfo, 0);
619 }
620}
Matt Spinlerb0a8df52020-07-07 14:41:06 -0500621
622// Prune PELs, when no HMC/OS/PHYP acks
623TEST_F(RepositoryTest, TestPruneNoAcks)
624{
625 Repository repo{repoPath, 4096 * 20, 100};
626
627 // Add 10 4096B (on disk) PELs of BMC nonInfo, Info and nonBMC info,
628 // nonInfo errors. None of them acked by PHYP, host, or HMC.
629 for (uint32_t i = 1; i <= 10; i++)
630 {
631 // BMC predictive
632 auto data = pelFactory(i, 'O', 0x20, 0x8800, 500);
633 auto pel = std::make_unique<PEL>(data);
634 repo.add(pel);
635
636 // BMC info
637 data = pelFactory(i + 100, 'O', 0x0, 0x8800, 500);
638 pel = std::make_unique<PEL>(data);
639 repo.add(pel);
640
641 // Hostboot predictive
642 data = pelFactory(i + 200, 'B', 0x20, 0x8800, 500);
643 pel = std::make_unique<PEL>(data);
644 repo.add(pel);
645
646 // Hostboot info
647 data = pelFactory(i + 300, 'B', 0x0, 0x8800, 500);
648 pel = std::make_unique<PEL>(data);
649 repo.add(pel);
650 }
651
652 const auto& sizes = repo.getSizeStats();
653 EXPECT_EQ(sizes.total, 4096 * 40);
654
655 // Sanity check the very first PELs with IDs 1 to 4 are
656 // there so we can check they are removed after the prune.
657 for (uint32_t i = 1; i < 5; i++)
658 {
659 Repository::LogID id{Repository::LogID::Pel{i}};
660 EXPECT_TRUE(repo.getPELAttributes(id));
661 }
662
663 // Prune down to 15%/30%/15%/30% = 90% total
664 auto IDs = repo.prune();
665
666 // Check the final sizes
667 EXPECT_EQ(sizes.total, 4096 * 18); // 90% of 20 PELs
668 EXPECT_EQ(sizes.bmcInfo, 4096 * 3); // 15% of 20 PELs
669 EXPECT_EQ(sizes.bmcServiceable, 4096 * 6); // 30% of 20 PELs
670 EXPECT_EQ(sizes.nonBMCInfo, 4096 * 3); // 15% of 20 PELs
671 EXPECT_EQ(sizes.nonBMCServiceable, 4096 * 6); // 30% of 20 PELs
672
673 // Check that at least the 4 oldest, which are the oldest of
674 // each type, were removed.
675 for (uint32_t i = 1; i < 5; i++)
676 {
677 Repository::LogID id{Repository::LogID::Pel{i}};
678 EXPECT_FALSE(repo.getPELAttributes(id));
679
680 // Make sure the corresponding OpenBMC event log ID which is
681 // 500 + the PEL ID is in the list.
682 EXPECT_TRUE(std::find(IDs.begin(), IDs.end(), 500 + i) != IDs.end());
683 }
684}
685
686// Test that if filled completely with 1 type of PEL, that
687// pruning still works properly
688TEST_F(RepositoryTest, TestPruneInfoOnly)
689{
690 Repository repo{repoPath, 4096 * 22, 100};
691
692 // Fill 4096*23 bytes on disk of BMC info PELs
693 for (uint32_t i = 1; i <= 23; i++)
694 {
695 auto data = pelFactory(i, 'O', 0, 0x8800, 1000);
696 auto pel = std::make_unique<PEL>(data);
697 repo.add(pel);
698 }
699
700 const auto& sizes = repo.getSizeStats();
701 EXPECT_EQ(sizes.total, 4096 * 23);
702
703 // Pruning to 15% of 4096 * 22 will leave 3 4096B PELs.
704
705 // Sanity check the oldest 20 are there so when they
706 // get pruned below we'll know they were removed.
707 for (uint32_t i = 1; i <= 20; i++)
708 {
709 Repository::LogID id{Repository::LogID::Pel{i}};
710 EXPECT_TRUE(repo.getPELAttributes(id));
711 }
712
713 auto IDs = repo.prune();
714
715 // Check the final sizes
716 EXPECT_EQ(sizes.total, 4096 * 3);
717 EXPECT_EQ(sizes.bmcInfo, 4096 * 3);
718 EXPECT_EQ(sizes.bmcServiceable, 0);
719 EXPECT_EQ(sizes.nonBMCInfo, 0);
720 EXPECT_EQ(sizes.nonBMCServiceable, 0);
721
722 EXPECT_EQ(IDs.size(), 20);
723
724 // Can no longer find the oldest 20 PELs.
725 for (uint32_t i = 1; i <= 20; i++)
726 {
727 Repository::LogID id{Repository::LogID::Pel{i}};
728 EXPECT_FALSE(repo.getPELAttributes(id));
729 EXPECT_TRUE(std::find(IDs.begin(), IDs.end(), 500 + i) != IDs.end());
730 }
731}
732
733// Test that the HMC/OS/PHYP ack values affect the
734// pruning order.
735TEST_F(RepositoryTest, TestPruneWithAcks)
736{
737 Repository repo{repoPath, 4096 * 20, 100};
738
739 // Fill 30% worth of BMC non-info non-acked PELs
740 for (uint32_t i = 1; i <= 6; i++)
741 {
742 // BMC predictive
743 auto data = pelFactory(i, 'O', 0x20, 0x8800, 500);
744 auto pel = std::make_unique<PEL>(data);
745 repo.add(pel);
746 }
747
748 // Add another PEL to push it over the 30%, each time adding
749 // a different type that should be pruned before the above ones
750 // even though those are older.
751 for (uint32_t i = 1; i <= 3; i++)
752 {
753 auto data = pelFactory(i, 'O', 0x20, 0x8800, 500);
754 auto pel = std::make_unique<PEL>(data);
755 auto idToDelete = pel->obmcLogID();
756 repo.add(pel);
757
758 if (0 == i)
759 {
760 repo.setPELHMCTransState(pel->id(), TransmissionState::acked);
761 }
762 else if (1 == i)
763 {
764 repo.setPELHostTransState(pel->id(), TransmissionState::acked);
765 }
766 else
767 {
768 repo.setPELHostTransState(pel->id(), TransmissionState::sent);
769 }
770
771 auto IDs = repo.prune();
772 EXPECT_EQ(repo.getSizeStats().total, 4096 * 6);
773
774 // The newest PEL should be the one deleted
775 ASSERT_EQ(IDs.size(), 1);
776 EXPECT_EQ(IDs[0], idToDelete);
777 }
778}
779
780// Test that the total number of PELs limit is enforced.
781TEST_F(RepositoryTest, TestPruneTooManyPELs)
782{
783 Repository repo{repoPath, 4096 * 100, 10};
784
785 // Add 10, which is the limit and is still OK
786 for (uint32_t i = 1; i <= 10; i++)
787 {
788 auto data = pelFactory(i, 'O', 0x20, 0x8800, 500);
789 auto pel = std::make_unique<PEL>(data);
790 repo.add(pel);
791 }
792
793 auto IDs = repo.prune();
794
795 // Nothing pruned yet
796 EXPECT_TRUE(IDs.empty());
797
798 // Add 1 more PEL which will be too many.
799 {
800 auto data = pelFactory(11, 'O', 0x20, 0x8800, 500);
801 auto pel = std::make_unique<PEL>(data);
802 repo.add(pel);
803 }
804
805 // Now that's it's over the limit of 10, it will bring it down
806 // to 80%, which is 8 after it removes 3.
807 IDs = repo.prune();
808 EXPECT_EQ(repo.getSizeStats().total, 4096 * 8);
809 ASSERT_EQ(IDs.size(), 3);
810
811 // Check that it deleted the oldest ones.
812 // The OpenBMC log ID is the PEL ID + 500.
813 EXPECT_EQ(IDs[0], 500 + 1);
814 EXPECT_EQ(IDs[1], 500 + 2);
815 EXPECT_EQ(IDs[2], 500 + 3);
816}
Matt Spinler7e727a32020-07-07 15:00:17 -0500817
818// Test the sizeWarning function
819TEST_F(RepositoryTest, TestSizeWarning)
820{
821 uint32_t id = 1;
822 Repository repo{repoPath, 100 * 4096, 500};
823
824 EXPECT_FALSE(repo.sizeWarning());
825
826 // 95% is still OK (disk size for these is 4096)
827 for (uint32_t i = 1; i <= 95; i++)
828 {
829 auto data = pelFactory(i, 'O', 0x20, 0x8800, 500);
830 auto pel = std::make_unique<PEL>(data);
831 repo.add(pel);
832 }
833
834 EXPECT_FALSE(repo.sizeWarning());
835
836 // Now at 96%
837 auto data = pelFactory(id++, 'B', 0x20, 0x8800, 400);
838 auto pel = std::make_unique<PEL>(data);
839 repo.add(pel);
840
841 EXPECT_TRUE(repo.sizeWarning());
842}
843
844// Test sizeWarning when there are too many PEls
845TEST_F(RepositoryTest, TestSizeWarningNumPELs)
846{
847 Repository repo{repoPath, 4096 * 100, 5};
848
849 EXPECT_FALSE(repo.sizeWarning());
850
851 for (uint32_t i = 1; i <= 5; i++)
852 {
853 auto data = pelFactory(i, 'O', 0x20, 0x8800, 500);
854 auto pel = std::make_unique<PEL>(data);
855 repo.add(pel);
856 }
857
858 EXPECT_FALSE(repo.sizeWarning());
859
860 // Add 1 more for a total of 6, now over the limit
861 {
862 auto data = pelFactory(6, 'O', 0x20, 0x8800, 500);
863 auto pel = std::make_unique<PEL>(data);
864 repo.add(pel);
865 }
866
867 EXPECT_TRUE(repo.sizeWarning());
868}