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