1*a1a69f19Skasunath #include "rde/rde_dictionary_manager.hpp"
2*a1a69f19Skasunath
3*a1a69f19Skasunath #include <cstring>
4*a1a69f19Skasunath #include <memory>
5*a1a69f19Skasunath #include <optional>
6*a1a69f19Skasunath #include <span>
7*a1a69f19Skasunath
8*a1a69f19Skasunath #include <gmock/gmock-matchers.h>
9*a1a69f19Skasunath #include <gmock/gmock.h>
10*a1a69f19Skasunath #include <gtest/gtest.h>
11*a1a69f19Skasunath
12*a1a69f19Skasunath namespace bios_bmc_smm_error_logger
13*a1a69f19Skasunath {
14*a1a69f19Skasunath namespace rde
15*a1a69f19Skasunath {
16*a1a69f19Skasunath
17*a1a69f19Skasunath constexpr std::array<uint8_t, 132> dummyDictionary1{
18*a1a69f19Skasunath {0x00, 0x03, 0x02, 0x00, 0x00, 0x00, 0x17, 0x01, 0x00, 0x00, 0x0, 0x0,
19*a1a69f19Skasunath 0xc, 0x0, 0x0, 0xf0, 0xf0, 0xf1, 0x17, 0x1, 0x0, 0x0, 0x0, 0x0,
20*a1a69f19Skasunath 0x0, 0x16, 0x0, 0x5, 0x0, 0xc, 0x84, 0x0, 0x14, 0x0, 0x0, 0x48,
21*a1a69f19Skasunath 0x0, 0x1, 0x0, 0x13, 0x90, 0x0, 0x56, 0x1, 0x0, 0x0, 0x0, 0x0,
22*a1a69f19Skasunath 0x0, 0x3, 0xa3, 0x0, 0x74, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x16,
23*a1a69f19Skasunath 0xa6, 0x0, 0x34, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x16, 0xbc, 0x0,
24*a1a69f19Skasunath 0x64, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x13, 0xd2, 0x0, 0x0, 0x0,
25*a1a69f19Skasunath 0x0, 0x52, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x74, 0x0, 0x0, 0x0,
26*a1a69f19Skasunath 0x0, 0x0, 0x0, 0xf, 0xe5, 0x0, 0x46, 0x1, 0x0, 0x66, 0x0, 0x3,
27*a1a69f19Skasunath 0x0, 0xb, 0xf4, 0x0, 0x50, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9,
28*a1a69f19Skasunath 0xff, 0x0, 0x50, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0x8, 0x1}};
29*a1a69f19Skasunath
30*a1a69f19Skasunath constexpr std::array<uint8_t, 14> dummyDictionary2{
31*a1a69f19Skasunath {0x65, 0x0, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x41, 0x72, 0x72, 0x61, 0x79,
32*a1a69f19Skasunath 0x50, 0x72}};
33*a1a69f19Skasunath
34*a1a69f19Skasunath class RdeDictionaryManagerTest : public ::testing::Test
35*a1a69f19Skasunath {
36*a1a69f19Skasunath protected:
37*a1a69f19Skasunath uint32_t resourceId = 1;
38*a1a69f19Skasunath DictionaryManager dm;
39*a1a69f19Skasunath };
40*a1a69f19Skasunath
TEST_F(RdeDictionaryManagerTest,DictionarySetTest)41*a1a69f19Skasunath TEST_F(RdeDictionaryManagerTest, DictionarySetTest)
42*a1a69f19Skasunath {
43*a1a69f19Skasunath // Add a single dictionary.
44*a1a69f19Skasunath dm.startDictionaryEntry(resourceId, std::span(dummyDictionary1));
45*a1a69f19Skasunath EXPECT_THAT(dm.getDictionaryCount(), 0);
46*a1a69f19Skasunath
47*a1a69f19Skasunath // Mark the dictionary as a valid dictionary.
48*a1a69f19Skasunath dm.markDataComplete(resourceId);
49*a1a69f19Skasunath EXPECT_THAT(dm.getDictionaryCount(), 1);
50*a1a69f19Skasunath
51*a1a69f19Skasunath // Request the dictionary back and verify the data.
52*a1a69f19Skasunath auto dataOrErr = dm.getDictionary(resourceId);
53*a1a69f19Skasunath EXPECT_TRUE(dataOrErr);
54*a1a69f19Skasunath EXPECT_THAT((*dataOrErr).size_bytes(), dummyDictionary1.size());
55*a1a69f19Skasunath EXPECT_THAT(memcmp((*dataOrErr).data(), dummyDictionary1.data(),
56*a1a69f19Skasunath dummyDictionary1.size()),
57*a1a69f19Skasunath 0);
58*a1a69f19Skasunath }
59*a1a69f19Skasunath
TEST_F(RdeDictionaryManagerTest,DictionaryNotSetTest)60*a1a69f19Skasunath TEST_F(RdeDictionaryManagerTest, DictionaryNotSetTest)
61*a1a69f19Skasunath {
62*a1a69f19Skasunath // Add a single dictionary.
63*a1a69f19Skasunath dm.startDictionaryEntry(resourceId, std::span(dummyDictionary1));
64*a1a69f19Skasunath EXPECT_THAT(dm.getDictionaryCount(), 0);
65*a1a69f19Skasunath // Request the dictionary back without marking it complete. Request should
66*a1a69f19Skasunath // fail.
67*a1a69f19Skasunath EXPECT_FALSE(dm.getDictionary(resourceId));
68*a1a69f19Skasunath }
69*a1a69f19Skasunath
TEST_F(RdeDictionaryManagerTest,DictionaryMultiSetTest)70*a1a69f19Skasunath TEST_F(RdeDictionaryManagerTest, DictionaryMultiSetTest)
71*a1a69f19Skasunath {
72*a1a69f19Skasunath // Creates a dictionary
73*a1a69f19Skasunath dm.startDictionaryEntry(resourceId, std::span(dummyDictionary1));
74*a1a69f19Skasunath EXPECT_THAT(dm.getDictionaryCount(), 0);
75*a1a69f19Skasunath dm.markDataComplete(resourceId);
76*a1a69f19Skasunath EXPECT_THAT(dm.getDictionaryCount(), 1);
77*a1a69f19Skasunath
78*a1a69f19Skasunath // Creates a second dictionary.
79*a1a69f19Skasunath dm.startDictionaryEntry(annotationResourceId, std::span(dummyDictionary2));
80*a1a69f19Skasunath dm.markDataComplete(annotationResourceId);
81*a1a69f19Skasunath EXPECT_THAT(dm.getDictionaryCount(), 2);
82*a1a69f19Skasunath
83*a1a69f19Skasunath auto data1OrErr = dm.getDictionary(resourceId);
84*a1a69f19Skasunath EXPECT_TRUE(data1OrErr);
85*a1a69f19Skasunath EXPECT_THAT((*data1OrErr).size_bytes(), dummyDictionary1.size());
86*a1a69f19Skasunath EXPECT_THAT(memcmp((*data1OrErr).data(), dummyDictionary1.data(),
87*a1a69f19Skasunath dummyDictionary1.size()),
88*a1a69f19Skasunath 0);
89*a1a69f19Skasunath
90*a1a69f19Skasunath auto data2OrErr = dm.getDictionary(annotationResourceId);
91*a1a69f19Skasunath EXPECT_TRUE(data2OrErr);
92*a1a69f19Skasunath EXPECT_THAT((*data2OrErr).size_bytes(), dummyDictionary2.size());
93*a1a69f19Skasunath EXPECT_THAT(memcmp((*data2OrErr).data(), dummyDictionary2.data(),
94*a1a69f19Skasunath dummyDictionary2.size()),
95*a1a69f19Skasunath 0);
96*a1a69f19Skasunath }
97*a1a69f19Skasunath
TEST_F(RdeDictionaryManagerTest,DictionaryOverwriteTest)98*a1a69f19Skasunath TEST_F(RdeDictionaryManagerTest, DictionaryOverwriteTest)
99*a1a69f19Skasunath {
100*a1a69f19Skasunath dm.startDictionaryEntry(resourceId, std::span(dummyDictionary2));
101*a1a69f19Skasunath
102*a1a69f19Skasunath // Recreate another one on the same location.
103*a1a69f19Skasunath dm.startDictionaryEntry(resourceId, std::span(dummyDictionary1));
104*a1a69f19Skasunath EXPECT_THAT(dm.getDictionaryCount(), 0);
105*a1a69f19Skasunath dm.markDataComplete(resourceId);
106*a1a69f19Skasunath EXPECT_THAT(dm.getDictionaryCount(), 1);
107*a1a69f19Skasunath
108*a1a69f19Skasunath auto dataOrErr = dm.getDictionary(resourceId);
109*a1a69f19Skasunath EXPECT_TRUE(dataOrErr);
110*a1a69f19Skasunath EXPECT_THAT((*dataOrErr).size_bytes(), dummyDictionary1.size());
111*a1a69f19Skasunath EXPECT_THAT(memcmp((*dataOrErr).data(), dummyDictionary1.data(),
112*a1a69f19Skasunath dummyDictionary1.size()),
113*a1a69f19Skasunath 0);
114*a1a69f19Skasunath
115*a1a69f19Skasunath // Recreate another one on the same location.
116*a1a69f19Skasunath dm.startDictionaryEntry(resourceId, std::span(dummyDictionary2));
117*a1a69f19Skasunath EXPECT_THAT(dm.getDictionaryCount(), 0);
118*a1a69f19Skasunath dm.markDataComplete(resourceId);
119*a1a69f19Skasunath EXPECT_THAT(dm.getDictionaryCount(), 1);
120*a1a69f19Skasunath
121*a1a69f19Skasunath auto newDataOrErr = dm.getDictionary(resourceId);
122*a1a69f19Skasunath EXPECT_TRUE(newDataOrErr);
123*a1a69f19Skasunath EXPECT_THAT((*newDataOrErr).size_bytes(), dummyDictionary2.size());
124*a1a69f19Skasunath EXPECT_THAT(memcmp((*newDataOrErr).data(), dummyDictionary2.data(),
125*a1a69f19Skasunath dummyDictionary2.size()),
126*a1a69f19Skasunath 0);
127*a1a69f19Skasunath }
128*a1a69f19Skasunath
TEST_F(RdeDictionaryManagerTest,DictionaryAppendDataTest)129*a1a69f19Skasunath TEST_F(RdeDictionaryManagerTest, DictionaryAppendDataTest)
130*a1a69f19Skasunath {
131*a1a69f19Skasunath // Creates a dictionary
132*a1a69f19Skasunath dm.startDictionaryEntry(resourceId, std::span(dummyDictionary1));
133*a1a69f19Skasunath EXPECT_THAT(dm.getDictionaryCount(), 0);
134*a1a69f19Skasunath
135*a1a69f19Skasunath // Lets copy the dictionary in two sizes.
136*a1a69f19Skasunath const uint32_t copySize1 = dummyDictionary2.size() / 2;
137*a1a69f19Skasunath const uint32_t copySize2 = dummyDictionary2.size() - copySize1;
138*a1a69f19Skasunath
139*a1a69f19Skasunath // Overwrite on the same location as before.
140*a1a69f19Skasunath dm.startDictionaryEntry(resourceId,
141*a1a69f19Skasunath std::span(dummyDictionary2.data(), copySize1));
142*a1a69f19Skasunath dm.addDictionaryData(
143*a1a69f19Skasunath resourceId, std::span(dummyDictionary2.data() + copySize1, copySize2));
144*a1a69f19Skasunath dm.markDataComplete(resourceId);
145*a1a69f19Skasunath EXPECT_THAT(dm.getDictionaryCount(), 1);
146*a1a69f19Skasunath
147*a1a69f19Skasunath auto dataOrErr = dm.getDictionary(resourceId);
148*a1a69f19Skasunath EXPECT_TRUE(dataOrErr);
149*a1a69f19Skasunath EXPECT_THAT((*dataOrErr).size_bytes(), dummyDictionary2.size());
150*a1a69f19Skasunath EXPECT_THAT(memcmp((*dataOrErr).data(), dummyDictionary2.data(),
151*a1a69f19Skasunath dummyDictionary2.size()),
152*a1a69f19Skasunath 0);
153*a1a69f19Skasunath }
154*a1a69f19Skasunath
TEST_F(RdeDictionaryManagerTest,DictionaryOverrideWithAddDataTest)155*a1a69f19Skasunath TEST_F(RdeDictionaryManagerTest, DictionaryOverrideWithAddDataTest)
156*a1a69f19Skasunath {
157*a1a69f19Skasunath dm.startDictionaryEntry(resourceId, std::span(dummyDictionary1));
158*a1a69f19Skasunath dm.markDataComplete(resourceId);
159*a1a69f19Skasunath EXPECT_THAT(dm.getDictionaryCount(), 1);
160*a1a69f19Skasunath
161*a1a69f19Skasunath dm.addDictionaryData(resourceId, std::span(dummyDictionary2));
162*a1a69f19Skasunath EXPECT_THAT(dm.getDictionaryCount(), 0);
163*a1a69f19Skasunath dm.markDataComplete(resourceId);
164*a1a69f19Skasunath EXPECT_THAT(dm.getDictionaryCount(), 1);
165*a1a69f19Skasunath }
166*a1a69f19Skasunath
TEST_F(RdeDictionaryManagerTest,DictionaryInvalidateTest)167*a1a69f19Skasunath TEST_F(RdeDictionaryManagerTest, DictionaryInvalidateTest)
168*a1a69f19Skasunath {
169*a1a69f19Skasunath dm.startDictionaryEntry(resourceId, std::span(dummyDictionary1));
170*a1a69f19Skasunath dm.markDataComplete(resourceId);
171*a1a69f19Skasunath EXPECT_THAT(dm.getDictionaryCount(), 1);
172*a1a69f19Skasunath
173*a1a69f19Skasunath dm.invalidateDictionaries();
174*a1a69f19Skasunath EXPECT_THAT(dm.getDictionaryCount(), 0);
175*a1a69f19Skasunath }
176*a1a69f19Skasunath
177*a1a69f19Skasunath } // namespace rde
178*a1a69f19Skasunath } // namespace bios_bmc_smm_error_logger
179