xref: /openbmc/libpldm/tests/dsp/bios_table.cpp (revision 615344fc)
1 #include <endian.h>
2 #include <libpldm/base.h>
3 #include <libpldm/bios.h>
4 #include <libpldm/bios_table.h>
5 #include <libpldm/utils.h>
6 
7 #include <algorithm>
8 #include <cstdint>
9 #include <cstring>
10 #include <iterator>
11 #include <string>
12 #include <utility>
13 #include <vector>
14 
15 #include <gmock/gmock.h>
16 #include <gtest/gtest.h>
17 
18 using testing::ElementsAreArray;
19 using Table = std::vector<uint8_t>;
20 
21 void buildTable(Table& table)
22 {
23     auto padSize = ((table.size() % 4) ? (4 - table.size() % 4) : 0);
24     table.insert(table.end(), padSize, 0);
25     uint32_t checksum = crc32(table.data(), table.size());
26     checksum = htole32(checksum);
27     uint8_t a[4];
28     std::memcpy(a, &checksum, sizeof(checksum));
29     table.insert(table.end(), std::begin(a), std::end(a));
30 }
31 
32 template <typename First, typename... Rest>
33 void buildTable(Table& table, First& first, Rest&... rest)
34 {
35     table.insert(table.end(), first.begin(), first.end());
36     buildTable(table, rest...);
37 }
38 
39 TEST(AttrTable, HeaderDecodeTest)
40 {
41     std::vector<uint8_t> enumEntry{
42         2, 0, /* attr handle */
43         0,    /* attr type */
44         1, 0, /* attr name handle (string handle) */
45         2,    /* number of possible value */
46         2, 0, /* possible value handle */
47         3, 0, /* possible value handle */
48         1,    /* number of default value */
49         0     /* default value string handle index */
50     };
51     auto entry =
52         reinterpret_cast<struct pldm_bios_attr_table_entry*>(enumEntry.data());
53     auto attrHandle = pldm_bios_table_attr_entry_decode_attribute_handle(entry);
54     EXPECT_EQ(attrHandle, 2);
55     auto attrType = pldm_bios_table_attr_entry_decode_attribute_type(entry);
56     EXPECT_EQ(attrType, 0);
57     auto stringHandle = pldm_bios_table_attr_entry_decode_string_handle(entry);
58     EXPECT_EQ(stringHandle, 1);
59 }
60 
61 TEST(AttrTable, EnumEntryDecodeTest)
62 {
63     std::vector<uint8_t> enumEntry{
64         0, 0, /* attr handle */
65         0,    /* attr type */
66         1, 0, /* attr name handle */
67         2,    /* number of possible value */
68         2, 0, /* possible value handle */
69         3, 0, /* possible value handle */
70         1,    /* number of default value */
71         1     /* default value string handle index */
72     };
73 
74     auto entry =
75         reinterpret_cast<struct pldm_bios_attr_table_entry*>(enumEntry.data());
76     uint8_t pvNumber;
77     ASSERT_EQ(pldm_bios_table_attr_entry_enum_decode_pv_num(entry, &pvNumber),
78               PLDM_SUCCESS);
79     EXPECT_EQ(pvNumber, 2);
80     pvNumber = 0;
81     auto rc = pldm_bios_table_attr_entry_enum_decode_pv_num(entry, &pvNumber);
82     EXPECT_EQ(rc, PLDM_SUCCESS);
83     EXPECT_EQ(pvNumber, 2);
84 
85     std::vector<uint16_t> pvHandles(pvNumber, 0);
86     ASSERT_EQ(pldm_bios_table_attr_entry_enum_decode_pv_hdls(
87                   entry, pvHandles.data(), pvHandles.size()),
88               PLDM_SUCCESS);
89     EXPECT_EQ(pvNumber, 2);
90     EXPECT_EQ(pvHandles[0], 2);
91     EXPECT_EQ(pvHandles[1], 3);
92     pvHandles.resize(1);
93     ASSERT_EQ(pldm_bios_table_attr_entry_enum_decode_pv_hdls(
94                   entry, pvHandles.data(), pvHandles.size()),
95               PLDM_SUCCESS);
96     EXPECT_EQ(pvHandles[0], 2);
97 
98     pvHandles.resize(2);
99     rc = pldm_bios_table_attr_entry_enum_decode_pv_hdls(entry, pvHandles.data(),
100                                                         pvHandles.size());
101     EXPECT_EQ(rc, PLDM_SUCCESS);
102     EXPECT_EQ(pvHandles[0], 2);
103     EXPECT_EQ(pvHandles[1], 3);
104     rc = pldm_bios_table_attr_entry_enum_decode_pv_hdls(entry, pvHandles.data(),
105                                                         1);
106     EXPECT_EQ(rc, PLDM_SUCCESS);
107 
108     uint8_t defNumber;
109     ASSERT_EQ(pldm_bios_table_attr_entry_enum_decode_def_num(entry, &defNumber),
110               PLDM_SUCCESS);
111     EXPECT_EQ(defNumber, 1);
112     std::vector<uint8_t> defIndices(defNumber);
113     rc = pldm_bios_table_attr_entry_enum_decode_def_indices(
114         entry, defIndices.data(), defIndices.size());
115     EXPECT_EQ(rc, defNumber);
116     EXPECT_THAT(defIndices, ElementsAreArray({1}));
117 
118     defNumber = 0;
119     rc = pldm_bios_table_attr_entry_enum_decode_def_num(entry, &defNumber);
120     EXPECT_EQ(rc, PLDM_SUCCESS);
121     EXPECT_EQ(defNumber, 1);
122 
123     rc = pldm_bios_table_attr_entry_enum_decode_pv_num(nullptr, &pvNumber);
124     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
125     rc = pldm_bios_table_attr_entry_enum_decode_def_num(entry, nullptr);
126     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
127 
128     entry->attr_type = PLDM_BIOS_STRING;
129     rc = pldm_bios_table_attr_entry_enum_decode_pv_num(entry, &pvNumber);
130     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
131 
132     rc = pldm_bios_table_attr_entry_enum_decode_def_num(entry, &defNumber);
133     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
134     rc = pldm_bios_table_attr_entry_enum_decode_pv_hdls(entry, nullptr, 0);
135     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
136 }
137 
138 TEST(AttrTable, EnumEntryEncodeTest)
139 {
140     std::vector<uint8_t> enumEntry{
141         0, 0, /* attr handle */
142         0,    /* attr type */
143         1, 0, /* attr name handle */
144         2,    /* number of possible value */
145         2, 0, /* possible value handle */
146         3, 0, /* possible value handle */
147         1,    /* number of default value */
148         0     /* default value string handle index */
149     };
150 
151     std::vector<uint16_t> pv_hdls{2, 3};
152     std::vector<uint8_t> defs{0};
153 
154     struct pldm_bios_table_attr_entry_enum_info info = {
155         1,              /* name handle */
156         false,          /* read only */
157         2,              /* pv number */
158         pv_hdls.data(), /* pv handle */
159         1,              /*def number */
160         defs.data()     /*def index*/
161     };
162     auto encodeLength = pldm_bios_table_attr_entry_enum_encode_length(2, 1);
163     EXPECT_EQ(encodeLength, enumEntry.size());
164 
165     std::vector<uint8_t> encodeEntry(encodeLength, 0);
166     ASSERT_EQ(pldm_bios_table_attr_entry_enum_encode(encodeEntry.data(),
167                                                      encodeEntry.size(), &info),
168               PLDM_SUCCESS);
169     // set attr handle = 0
170     encodeEntry[0] = 0;
171     encodeEntry[1] = 0;
172 
173     EXPECT_EQ(enumEntry, encodeEntry);
174 
175     EXPECT_NE(pldm_bios_table_attr_entry_enum_encode(
176                   encodeEntry.data(), encodeEntry.size() - 1, &info),
177               PLDM_SUCCESS);
178     auto rc = pldm_bios_table_attr_entry_enum_encode(encodeEntry.data(),
179                                                      encodeEntry.size(), &info);
180     EXPECT_EQ(rc, PLDM_SUCCESS);
181     // set attr handle = 0
182     encodeEntry[0] = 0;
183     encodeEntry[1] = 0;
184 
185     EXPECT_EQ(enumEntry, encodeEntry);
186     rc = pldm_bios_table_attr_entry_enum_encode(encodeEntry.data(),
187                                                 encodeEntry.size() - 1, &info);
188     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
189 }
190 
191 TEST(AttrTable, StringEntryDecodeTest)
192 {
193     std::vector<uint8_t> stringEntry{
194         1,   0,       /* attr handle */
195         1,            /* attr type */
196         12,  0,       /* attr name handle */
197         1,            /* string type */
198         1,   0,       /* minimum length of the string in bytes */
199         100, 0,       /* maximum length of the string in bytes */
200         3,   0,       /* length of default string in length */
201         'a', 'b', 'c' /* default string  */
202     };
203 
204     auto entry = reinterpret_cast<struct pldm_bios_attr_table_entry*>(
205         stringEntry.data());
206     auto stringType =
207         pldm_bios_table_attr_entry_string_decode_string_type(entry);
208     EXPECT_EQ(stringType, 1);
209     auto minLength = pldm_bios_table_attr_entry_string_decode_min_length(entry);
210     EXPECT_EQ(minLength, 1);
211     auto maxLength = pldm_bios_table_attr_entry_string_decode_max_length(entry);
212     EXPECT_EQ(maxLength, 100);
213 
214     uint16_t defStringLength;
215     ASSERT_EQ(pldm_bios_table_attr_entry_string_decode_def_string_length(
216                   entry, &defStringLength),
217               PLDM_SUCCESS);
218     EXPECT_EQ(defStringLength, 3);
219     std::vector<char> defString(defStringLength + 1);
220     auto rc = pldm_bios_table_attr_entry_string_decode_def_string(
221         entry, defString.data(), defString.size());
222     EXPECT_EQ(rc, 3);
223     EXPECT_STREQ(defString.data(), "abc");
224     rc = pldm_bios_table_attr_entry_string_decode_def_string(
225         entry, defString.data(), defString.size() - 1);
226     EXPECT_EQ(rc, 2);
227     EXPECT_STREQ(defString.data(), "ab");
228 
229     defStringLength = 0;
230     rc = pldm_bios_table_attr_entry_string_decode_def_string_length(
231         entry, &defStringLength);
232     EXPECT_EQ(rc, PLDM_SUCCESS);
233     EXPECT_EQ(defStringLength, 3);
234 
235     rc = pldm_bios_table_attr_entry_string_decode_def_string_length(entry,
236                                                                     nullptr);
237     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
238     rc = pldm_bios_table_attr_entry_string_decode_def_string_length(
239         nullptr, &defStringLength);
240     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
241     entry->attr_type = PLDM_BIOS_INTEGER;
242     rc = pldm_bios_table_attr_entry_string_decode_def_string_length(
243         entry, &defStringLength);
244     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
245     rc = pldm_bios_table_attr_entry_string_decode_def_string_length(
246         nullptr, &defStringLength);
247     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
248 }
249 
250 TEST(AttrTable, StringEntryEncodeTest)
251 {
252     std::vector<uint8_t> stringEntry{
253         0,   0,        /* attr handle */
254         1,             /* attr type */
255         3,   0,        /* attr name handle */
256         1,             /* string type */
257         1,   0,        /* min string length */
258         100, 0,        /* max string length */
259         3,   0,        /* default string length */
260         'a', 'b', 'c', /* default string */
261     };
262 
263     struct pldm_bios_table_attr_entry_string_info info = {
264         3,     /* name handle */
265         false, /* read only */
266         1,     /* string type ascii */
267         1,     /* min length */
268         100,   /* max length */
269         3,     /* def length */
270         "abc", /* def string */
271     };
272     auto encodeLength = pldm_bios_table_attr_entry_string_encode_length(3);
273     EXPECT_EQ(encodeLength, stringEntry.size());
274 
275     std::vector<uint8_t> encodeEntry(encodeLength, 0);
276     ASSERT_EQ(pldm_bios_table_attr_entry_string_encode(
277                   encodeEntry.data(), encodeEntry.size(), &info),
278               PLDM_SUCCESS);
279     // set attr handle = 0
280     encodeEntry[0] = 0;
281     encodeEntry[1] = 0;
282 
283     EXPECT_EQ(stringEntry, encodeEntry);
284 
285     EXPECT_NE(pldm_bios_table_attr_entry_string_encode(
286                   encodeEntry.data(), encodeEntry.size() - 1, &info),
287               PLDM_SUCCESS);
288     auto rc = pldm_bios_table_attr_entry_string_encode(
289         encodeEntry.data(), encodeEntry.size(), &info);
290     EXPECT_EQ(rc, PLDM_SUCCESS);
291     // set attr handle = 0
292     encodeEntry[0] = 0;
293     encodeEntry[1] = 0;
294 
295     EXPECT_EQ(stringEntry, encodeEntry);
296     rc = pldm_bios_table_attr_entry_string_encode(
297         encodeEntry.data(), encodeEntry.size() - 1, &info);
298     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
299     std::swap(info.max_length, info.min_length);
300     const char* errmsg;
301     rc = pldm_bios_table_attr_entry_string_info_check(&info, &errmsg);
302     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
303     EXPECT_STREQ(
304         "MinimumStingLength should not be greater than MaximumStringLength",
305         errmsg);
306     rc = pldm_bios_table_attr_entry_string_encode(encodeEntry.data(),
307                                                   encodeEntry.size(), &info);
308     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
309     std::swap(info.max_length, info.min_length);
310 
311     std::vector<uint8_t> stringEntryLength0{
312         0,   0, /* attr handle */
313         1,      /* attr type */
314         3,   0, /* attr name handle */
315         1,      /* string type */
316         0,   0, /* min string length */
317         100, 0, /* max string length */
318         0,   0, /* default string length */
319     };
320 
321     info.min_length = 0;
322     info.def_length = 0;
323     info.def_string = nullptr;
324 
325     encodeLength = pldm_bios_table_attr_entry_string_encode_length(0);
326     EXPECT_EQ(encodeLength, stringEntryLength0.size());
327 
328     encodeEntry.resize(encodeLength);
329     ASSERT_EQ(pldm_bios_table_attr_entry_string_encode(
330                   encodeEntry.data(), encodeEntry.size(), &info),
331               PLDM_SUCCESS);
332     // set attr handle = 0
333     encodeEntry[0] = 0;
334     encodeEntry[1] = 0;
335 
336     EXPECT_EQ(stringEntryLength0, encodeEntry);
337 }
338 
339 TEST(AttrTable, integerEntryEncodeTest)
340 {
341     std::vector<uint8_t> integerEntry{
342         0,  0,                   /* attr handle */
343         3,                       /* attr type */
344         1,  0,                   /* attr name handle */
345         1,  0, 0, 0, 0, 0, 0, 0, /* lower bound */
346         10, 0, 0, 0, 0, 0, 0, 0, /* upper bound */
347         2,  0, 0, 0,             /* scalar increment */
348         3,  0, 0, 0, 0, 0, 0, 0, /* default value */
349     };
350 
351     std::vector<uint16_t> pv_hdls{2, 3};
352     std::vector<uint8_t> defs{0};
353 
354     struct pldm_bios_table_attr_entry_integer_info info = {
355         1,     /* name handle */
356         false, /* read only */
357         1,     /* lower bound */
358         10,    /* upper bound */
359         2,     /* scalar increment */
360         3      /* default value */
361     };
362     auto encodeLength = pldm_bios_table_attr_entry_integer_encode_length();
363     EXPECT_EQ(encodeLength, integerEntry.size());
364 
365     std::vector<uint8_t> encodeEntry(encodeLength, 0);
366     ASSERT_EQ(pldm_bios_table_attr_entry_integer_encode(
367                   encodeEntry.data(), encodeEntry.size(), &info),
368               PLDM_SUCCESS);
369     // set attr handle = 0
370     encodeEntry[0] = 0;
371     encodeEntry[1] = 0;
372 
373     EXPECT_EQ(integerEntry, encodeEntry);
374 
375     EXPECT_NE(pldm_bios_table_attr_entry_integer_encode(
376                   encodeEntry.data(), encodeEntry.size() - 1, &info),
377               PLDM_SUCCESS);
378 
379     auto rc = pldm_bios_table_attr_entry_integer_encode(
380         encodeEntry.data(), encodeEntry.size(), &info);
381     EXPECT_EQ(rc, PLDM_SUCCESS);
382     // set attr handle = 0
383     encodeEntry[0] = 0;
384     encodeEntry[1] = 0;
385 
386     EXPECT_EQ(integerEntry, encodeEntry);
387 
388     rc = pldm_bios_table_attr_entry_integer_encode(
389         encodeEntry.data(), encodeEntry.size() - 1, &info);
390     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
391 
392     info.lower_bound = 100;
393     info.upper_bound = 50;
394     const char* errmsg;
395     rc = pldm_bios_table_attr_entry_integer_info_check(&info, &errmsg);
396     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
397     EXPECT_STREQ("LowerBound should not be greater than UpperBound", errmsg);
398     rc = pldm_bios_table_attr_entry_integer_encode(encodeEntry.data(),
399                                                    encodeEntry.size(), &info);
400     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
401 }
402 
403 TEST(AttrTable, integerEntryDecodeTest)
404 {
405     std::vector<uint8_t> integerEntry{
406         0,  0,                   /* attr handle */
407         3,                       /* attr type */
408         1,  0,                   /* attr name handle */
409         1,  0, 0, 0, 0, 0, 0, 0, /* lower bound */
410         10, 0, 0, 0, 0, 0, 0, 0, /* upper bound */
411         2,  0, 0, 0,             /* scalar increment */
412         3,  0, 0, 0, 0, 0, 0, 0, /* default value */
413     };
414 
415     uint64_t lower;
416     uint64_t upper;
417     uint64_t def;
418     uint32_t scalar;
419     auto entry = reinterpret_cast<struct pldm_bios_attr_table_entry*>(
420         integerEntry.data());
421     pldm_bios_table_attr_entry_integer_decode(entry, &lower, &upper, &scalar,
422                                               &def);
423     EXPECT_EQ(lower, 1u);
424     EXPECT_EQ(upper, 10u);
425     EXPECT_EQ(scalar, 2u);
426     EXPECT_EQ(def, 3u);
427 }
428 
429 TEST(AttrTable, ItearatorTest)
430 {
431     std::vector<uint8_t> enumEntry{
432         0, 0, /* attr handle */
433         0,    /* attr type */
434         1, 0, /* attr name handle */
435         2,    /* number of possible value */
436         2, 0, /* possible value handle */
437         3, 0, /* possible value handle */
438         1,    /* number of default value */
439         0     /* default value string handle index */
440     };
441     std::vector<uint8_t> stringEntry{
442         1,   0,       /* attr handle */
443         1,            /* attr type */
444         12,  0,       /* attr name handle */
445         1,            /* string type */
446         1,   0,       /* minimum length of the string in bytes */
447         100, 0,       /* maximum length of the string in bytes */
448         3,   0,       /* length of default string in length */
449         'a', 'b', 'c' /* default string  */
450     };
451     std::vector<uint8_t> integerEntry{
452         0,  0,                   /* attr handle */
453         3,                       /* attr type */
454         1,  0,                   /* attr name handle */
455         1,  0, 0, 0, 0, 0, 0, 0, /* lower bound */
456         10, 0, 0, 0, 0, 0, 0, 0, /* upper bound */
457         2,  0, 0, 0,             /* scalar increment */
458         3,  0, 0, 0, 0, 0, 0, 0, /* default value */
459     };
460 
461     Table table;
462     buildTable(table, enumEntry, stringEntry, integerEntry, enumEntry);
463     auto iter = pldm_bios_table_iter_create(table.data(), table.size(),
464                                             PLDM_BIOS_ATTR_TABLE);
465     auto entry = pldm_bios_table_iter_attr_entry_value(iter);
466     auto rc = std::memcmp(entry, enumEntry.data(), enumEntry.size());
467     EXPECT_EQ(rc, 0);
468 
469     pldm_bios_table_iter_next(iter);
470     entry = pldm_bios_table_iter_attr_entry_value(iter);
471     rc = std::memcmp(entry, stringEntry.data(), stringEntry.size());
472     EXPECT_EQ(rc, 0);
473 
474     pldm_bios_table_iter_next(iter);
475     entry = pldm_bios_table_iter_attr_entry_value(iter);
476     rc = std::memcmp(entry, integerEntry.data(), integerEntry.size());
477     EXPECT_EQ(rc, 0);
478 
479     pldm_bios_table_iter_next(iter);
480     entry = pldm_bios_table_iter_attr_entry_value(iter);
481     rc = std::memcmp(entry, enumEntry.data(), enumEntry.size());
482     EXPECT_EQ(rc, 0);
483 
484     pldm_bios_table_iter_next(iter);
485     EXPECT_TRUE(pldm_bios_table_iter_is_end(iter));
486     pldm_bios_table_iter_free(iter);
487 }
488 
489 TEST(AttrTable, FindTest)
490 {
491     std::vector<uint8_t> enumEntry{
492         0, 0, /* attr handle */
493         0,    /* attr type */
494         1, 0, /* attr name handle */
495         2,    /* number of possible value */
496         2, 0, /* possible value handle */
497         3, 0, /* possible value handle */
498         1,    /* number of default value */
499         0     /* default value string handle index */
500     };
501     std::vector<uint8_t> stringEntry{
502         1,   0,       /* attr handle */
503         1,            /* attr type */
504         2,   0,       /* attr name handle */
505         1,            /* string type */
506         1,   0,       /* minimum length of the string in bytes */
507         100, 0,       /* maximum length of the string in bytes */
508         3,   0,       /* length of default string in length */
509         'a', 'b', 'c' /* default string  */
510     };
511     std::vector<uint8_t> integerEntry{
512         0,  0,                   /* attr handle */
513         3,                       /* attr type */
514         3,  0,                   /* attr name handle */
515         1,  0, 0, 0, 0, 0, 0, 0, /* lower bound */
516         10, 0, 0, 0, 0, 0, 0, 0, /* upper bound */
517         2,  0, 0, 0,             /* scalar increment */
518         3,  0, 0, 0, 0, 0, 0, 0, /* default value */
519     };
520 
521     Table table;
522     buildTable(table, enumEntry, stringEntry, integerEntry, enumEntry);
523 
524     auto entry =
525         pldm_bios_table_attr_find_by_handle(table.data(), table.size(), 1);
526     EXPECT_NE(entry, nullptr);
527     auto p = reinterpret_cast<const uint8_t*>(entry);
528     EXPECT_THAT(std::vector<uint8_t>(p, p + stringEntry.size()),
529                 ElementsAreArray(stringEntry));
530 
531     entry = pldm_bios_table_attr_find_by_handle(table.data(), table.size(), 3);
532     EXPECT_EQ(entry, nullptr);
533 
534     entry = pldm_bios_table_attr_find_by_string_handle(table.data(),
535                                                        table.size(), 2);
536     EXPECT_NE(entry, nullptr);
537     p = reinterpret_cast<const uint8_t*>(entry);
538     EXPECT_THAT(std::vector<uint8_t>(p, p + stringEntry.size()),
539                 ElementsAreArray(stringEntry));
540 
541     entry = pldm_bios_table_attr_find_by_string_handle(table.data(),
542                                                        table.size(), 4);
543     EXPECT_EQ(entry, nullptr);
544 }
545 
546 TEST(AttrValTable, HeaderDecodeTest)
547 {
548     std::vector<uint8_t> enumEntry{
549         1, 0, /* attr handle */
550         0,    /* attr type */
551         2,    /* number of current value */
552         0,    /* current value string handle index */
553         1,    /* current value string handle index */
554     };
555     auto entry = reinterpret_cast<struct pldm_bios_attr_val_table_entry*>(
556         enumEntry.data());
557     auto attrHandle =
558         pldm_bios_table_attr_value_entry_decode_attribute_handle(entry);
559     EXPECT_EQ(attrHandle, 1);
560     auto attrType =
561         pldm_bios_table_attr_value_entry_decode_attribute_type(entry);
562     EXPECT_EQ(attrType, 0);
563 }
564 
565 TEST(AttrValTable, EnumEntryEncodeTest)
566 {
567     std::vector<uint8_t> enumEntry{
568         0, 0, /* attr handle */
569         0,    /* attr type */
570         2,    /* number of current value */
571         0,    /* current value string handle index */
572         1,    /* current value string handle index */
573     };
574 
575     auto length = pldm_bios_table_attr_value_entry_encode_enum_length(2);
576     EXPECT_EQ(length, enumEntry.size());
577     std::vector<uint8_t> encodeEntry(length, 0);
578     uint8_t handles[] = {0, 1};
579     ASSERT_EQ(pldm_bios_table_attr_value_entry_encode_enum(
580                   encodeEntry.data(), encodeEntry.size(), 0, 0, 2, handles),
581               PLDM_SUCCESS);
582     EXPECT_EQ(encodeEntry, enumEntry);
583 
584     EXPECT_NE(pldm_bios_table_attr_value_entry_encode_enum(
585                   encodeEntry.data(), encodeEntry.size() - 1, 0, 0, 2, handles),
586               PLDM_SUCCESS);
587 
588     auto rc = pldm_bios_table_attr_value_entry_encode_enum(
589         encodeEntry.data(), encodeEntry.size(), 0, PLDM_BIOS_ENUMERATION, 2,
590         handles);
591     EXPECT_EQ(rc, PLDM_SUCCESS);
592     EXPECT_EQ(encodeEntry, enumEntry);
593     auto entry = reinterpret_cast<struct pldm_bios_attr_val_table_entry*>(
594         enumEntry.data());
595     entry->attr_type = PLDM_BIOS_ENUMERATION_READ_ONLY;
596     rc = pldm_bios_table_attr_value_entry_encode_enum(
597         encodeEntry.data(), encodeEntry.size(), 0,
598         PLDM_BIOS_ENUMERATION_READ_ONLY, 2, handles);
599     EXPECT_EQ(rc, PLDM_SUCCESS);
600     EXPECT_EQ(encodeEntry, enumEntry);
601     rc = pldm_bios_table_attr_value_entry_encode_enum(
602         encodeEntry.data(), encodeEntry.size(), 0, PLDM_BIOS_PASSWORD, 2,
603         handles);
604     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
605     rc = pldm_bios_table_attr_value_entry_encode_enum(
606         encodeEntry.data(), encodeEntry.size() - 1, 0, PLDM_BIOS_ENUMERATION, 2,
607         handles);
608     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
609 }
610 
611 TEST(AttrValTable, EnumEntryDecodeTest)
612 {
613     std::vector<uint8_t> enumEntry{
614         0, 0, /* attr handle */
615         0,    /* attr type */
616         2,    /* number of current value */
617         0,    /* current value string handle index */
618         1,    /* current value string handle index */
619     };
620 
621     auto entry = reinterpret_cast<struct pldm_bios_attr_val_table_entry*>(
622         enumEntry.data());
623     auto number = pldm_bios_table_attr_value_entry_enum_decode_number(entry);
624     EXPECT_EQ(2, number);
625 
626     std::vector<uint8_t> handles(2, 0);
627     auto rc = pldm_bios_table_attr_value_entry_enum_decode_handles(
628         entry, handles.data(), handles.size());
629     EXPECT_EQ(rc, 2);
630     EXPECT_EQ(handles[0], 0);
631     EXPECT_EQ(handles[1], 1);
632 
633     /* Buffer size is more than the number of current string handles */
634     std::vector<uint8_t> handleIndexes(3, 0);
635     rc = pldm_bios_table_attr_value_entry_enum_decode_handles(
636         entry, handleIndexes.data(), handleIndexes.size());
637     EXPECT_EQ(rc, 2);
638     EXPECT_EQ(handleIndexes[0], 0);
639     EXPECT_EQ(handleIndexes[1], 1);
640 
641     /* Buffersize is less than the number of current string handles */
642     std::vector<uint8_t> strHandles(1, 0);
643     rc = pldm_bios_table_attr_value_entry_enum_decode_handles(
644         entry, strHandles.data(), strHandles.size());
645     EXPECT_EQ(rc, 1);
646     EXPECT_EQ(strHandles[0], 0);
647 }
648 
649 TEST(AttrValTable, stringEntryEncodeTest)
650 {
651     std::vector<uint8_t> stringEntry{
652         0,   0,        /* attr handle */
653         1,             /* attr type */
654         3,   0,        /* current string length */
655         'a', 'b', 'c', /* default value string handle index */
656     };
657 
658     auto length = pldm_bios_table_attr_value_entry_encode_string_length(3);
659     EXPECT_EQ(length, stringEntry.size());
660     std::vector<uint8_t> encodeEntry(length, 0);
661     ASSERT_EQ(pldm_bios_table_attr_value_entry_encode_string(
662                   encodeEntry.data(), encodeEntry.size(), 0, 1, 3, "abc"),
663               PLDM_SUCCESS);
664     EXPECT_EQ(encodeEntry, stringEntry);
665 
666     EXPECT_NE(pldm_bios_table_attr_value_entry_encode_string(
667                   encodeEntry.data(), encodeEntry.size() - 1, 0, 1, 3, "abc"),
668               PLDM_SUCCESS);
669 
670     auto rc = pldm_bios_table_attr_value_entry_encode_string(
671         encodeEntry.data(), encodeEntry.size(), 0, PLDM_BIOS_STRING, 3, "abc");
672     EXPECT_EQ(rc, PLDM_SUCCESS);
673     EXPECT_EQ(encodeEntry, stringEntry);
674     auto entry = reinterpret_cast<struct pldm_bios_attr_val_table_entry*>(
675         stringEntry.data());
676     entry->attr_type = PLDM_BIOS_STRING_READ_ONLY;
677     rc = pldm_bios_table_attr_value_entry_encode_string(
678         encodeEntry.data(), encodeEntry.size(), 0, PLDM_BIOS_STRING_READ_ONLY,
679         3, "abc");
680     EXPECT_EQ(rc, PLDM_SUCCESS);
681     EXPECT_EQ(encodeEntry, stringEntry);
682     rc = pldm_bios_table_attr_value_entry_encode_string(
683         encodeEntry.data(), encodeEntry.size(), 0, PLDM_BIOS_PASSWORD, 3,
684         "abc");
685     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
686     rc = pldm_bios_table_attr_value_entry_encode_string(
687         encodeEntry.data(), encodeEntry.size() - 1, 0, PLDM_BIOS_STRING, 3,
688         "abc");
689     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
690 }
691 
692 TEST(AttrValTable, StringEntryDecodeTest)
693 {
694     std::vector<uint8_t> stringEntry{
695         0,   0,        /* attr handle */
696         1,             /* attr type */
697         3,   0,        /* current string length */
698         'a', 'b', 'c', /* default value string handle index */
699     };
700 
701     auto entry = reinterpret_cast<struct pldm_bios_attr_val_table_entry*>(
702         stringEntry.data());
703     auto length = pldm_bios_table_attr_value_entry_string_decode_length(entry);
704     EXPECT_EQ(3, length);
705 
706     auto handle = pldm_bios_table_attr_value_entry_decode_handle(entry);
707     EXPECT_EQ(0, handle);
708 
709     auto entryLength = pldm_bios_table_attr_value_entry_length(entry);
710     EXPECT_EQ(stringEntry.size(), entryLength);
711 
712     variable_field currentString{};
713     pldm_bios_table_attr_value_entry_string_decode_string(entry,
714                                                           &currentString);
715     EXPECT_THAT(std::vector<uint8_t>(currentString.ptr,
716                                      currentString.ptr + currentString.length),
717                 ElementsAreArray(std::vector<uint8_t>{'a', 'b', 'c'}));
718 }
719 
720 TEST(AttrValTable, integerEntryEncodeTest)
721 {
722     std::vector<uint8_t> integerEntry{
723         0,  0,                   /* attr handle */
724         3,                       /* attr type */
725         10, 0, 0, 0, 0, 0, 0, 0, /* current value */
726     };
727 
728     auto length = pldm_bios_table_attr_value_entry_encode_integer_length();
729     EXPECT_EQ(length, integerEntry.size());
730     std::vector<uint8_t> encodeEntry(length, 0);
731     ASSERT_EQ(
732         pldm_bios_table_attr_value_entry_encode_integer(
733             encodeEntry.data(), encodeEntry.size(), 0, PLDM_BIOS_INTEGER, 10),
734         PLDM_SUCCESS);
735     EXPECT_EQ(encodeEntry, integerEntry);
736 
737     EXPECT_NE(pldm_bios_table_attr_value_entry_encode_integer(
738                   encodeEntry.data(), encodeEntry.size() - 1, 0,
739                   PLDM_BIOS_INTEGER, 10),
740               PLDM_SUCCESS);
741 
742     auto rc = pldm_bios_table_attr_value_entry_encode_integer(
743         encodeEntry.data(), encodeEntry.size(), 0, PLDM_BIOS_INTEGER, 10);
744     EXPECT_EQ(rc, PLDM_SUCCESS);
745     EXPECT_EQ(encodeEntry, integerEntry);
746     auto entry = reinterpret_cast<struct pldm_bios_attr_val_table_entry*>(
747         integerEntry.data());
748     entry->attr_type = PLDM_BIOS_INTEGER_READ_ONLY;
749     rc = pldm_bios_table_attr_value_entry_encode_integer(
750         encodeEntry.data(), encodeEntry.size(), 0, PLDM_BIOS_INTEGER_READ_ONLY,
751         10);
752     EXPECT_EQ(rc, PLDM_SUCCESS);
753     EXPECT_EQ(encodeEntry, integerEntry);
754 
755     rc = pldm_bios_table_attr_value_entry_encode_integer(
756         encodeEntry.data(), encodeEntry.size(), 0, PLDM_BIOS_PASSWORD, 10);
757     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
758     rc = pldm_bios_table_attr_value_entry_encode_integer(
759         encodeEntry.data(), encodeEntry.size() - 1, 0,
760         PLDM_BIOS_INTEGER_READ_ONLY, 10);
761     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
762 }
763 
764 TEST(AttrValTable, integerEntryDecodeTest)
765 {
766     std::vector<uint8_t> integerEntry{
767         0,  0,                   /* attr handle */
768         3,                       /* attr type */
769         10, 0, 0, 0, 0, 0, 0, 0, /* current value */
770     };
771 
772     auto entry = reinterpret_cast<struct pldm_bios_attr_val_table_entry*>(
773         integerEntry.data());
774     auto cv = pldm_bios_table_attr_value_entry_integer_decode_cv(entry);
775     EXPECT_EQ(cv, 10u);
776 }
777 
778 TEST(AttrValTable, IteratorTest)
779 {
780     std::vector<uint8_t> enumEntry{
781         0, 0, /* attr handle */
782         0,    /* attr type */
783         2,    /* number of current value */
784         0,    /* current value string handle index */
785         1,    /* current value string handle index */
786     };
787     std::vector<uint8_t> stringEntry{
788         0,   0,        /* attr handle */
789         1,             /* attr type */
790         3,   0,        /* current string length */
791         'a', 'b', 'c', /* default value string handle index */
792     };
793     std::vector<uint8_t> integerEntry{
794         0,  0,                   /* attr handle */
795         3,                       /* attr type */
796         10, 0, 0, 0, 0, 0, 0, 0, /* current value */
797     };
798 
799     Table table;
800     buildTable(table, enumEntry, stringEntry, integerEntry, enumEntry);
801 
802     auto iter = pldm_bios_table_iter_create(table.data(), table.size(),
803                                             PLDM_BIOS_ATTR_VAL_TABLE);
804     auto entry = pldm_bios_table_iter_attr_value_entry_value(iter);
805 
806     auto p = reinterpret_cast<const uint8_t*>(entry);
807     EXPECT_THAT(std::vector<uint8_t>(p, p + enumEntry.size()),
808                 ElementsAreArray(enumEntry));
809 
810     pldm_bios_table_iter_next(iter);
811     entry = pldm_bios_table_iter_attr_value_entry_value(iter);
812     p = reinterpret_cast<const uint8_t*>(entry);
813     EXPECT_THAT(std::vector<uint8_t>(p, p + stringEntry.size()),
814                 ElementsAreArray(stringEntry));
815 
816     pldm_bios_table_iter_next(iter);
817     entry = pldm_bios_table_iter_attr_value_entry_value(iter);
818     p = reinterpret_cast<const uint8_t*>(entry);
819     EXPECT_THAT(std::vector<uint8_t>(p, p + integerEntry.size()),
820                 ElementsAreArray(integerEntry));
821 
822     pldm_bios_table_iter_next(iter);
823     entry = pldm_bios_table_iter_attr_value_entry_value(iter);
824     p = reinterpret_cast<const uint8_t*>(entry);
825     EXPECT_THAT(std::vector<uint8_t>(p, p + enumEntry.size()),
826                 ElementsAreArray(enumEntry));
827 
828     pldm_bios_table_iter_next(iter);
829     EXPECT_TRUE(pldm_bios_table_iter_is_end(iter));
830 
831     pldm_bios_table_iter_free(iter);
832 }
833 
834 TEST(AttrValTable, FindTest)
835 {
836     std::vector<uint8_t> enumEntry{
837         0, 0, /* attr handle */
838         0,    /* attr type */
839         2,    /* number of current value */
840         0,    /* current value string handle index */
841         1,    /* current value string handle index */
842     };
843     std::vector<uint8_t> stringEntry{
844         1,   0,        /* attr handle */
845         1,             /* attr type */
846         3,   0,        /* current string length */
847         'a', 'b', 'c', /* default value string handle index */
848     };
849     std::vector<uint8_t> integerEntry{
850         2,  0,                   /* attr handle */
851         3,                       /* attr type */
852         10, 0, 0, 0, 0, 0, 0, 0, /* current value */
853     };
854 
855     Table table;
856     buildTable(table, enumEntry, stringEntry, integerEntry);
857 
858     auto entry = pldm_bios_table_attr_value_find_by_handle(table.data(),
859                                                            table.size(), 1);
860     EXPECT_NE(entry, nullptr);
861     auto p = reinterpret_cast<const uint8_t*>(entry);
862     EXPECT_THAT(std::vector<uint8_t>(p, p + stringEntry.size()),
863                 ElementsAreArray(stringEntry));
864 
865     entry = pldm_bios_table_attr_value_find_by_handle(table.data(),
866                                                       table.size(), 3);
867     EXPECT_EQ(entry, nullptr);
868 
869     auto firstEntry =
870         reinterpret_cast<struct pldm_bios_attr_val_table_entry*>(table.data());
871     firstEntry->attr_type = PLDM_BIOS_PASSWORD;
872 #ifdef NDEBUG
873     EXPECT_EQ(pldm_bios_table_attr_value_find_by_handle(table.data(),
874                                                         table.size(), 1),
875               nullptr);
876 #else
877     EXPECT_DEATH(pldm_bios_table_attr_value_find_by_handle(table.data(),
878                                                            table.size(), 1),
879                  "entry_length != NULL");
880 #endif
881 }
882 
883 TEST(AttrValTable, CopyAndUpdateTest)
884 {
885     std::vector<uint8_t> enumEntry{
886         0, 0, /* attr handle */
887         0,    /* attr type */
888         2,    /* number of current value */
889         0,    /* current value string handle index */
890         1,    /* current value string handle index */
891     };
892     std::vector<uint8_t> stringEntry{
893         1,   0,        /* attr handle */
894         1,             /* attr type */
895         3,   0,        /* current string length */
896         'a', 'b', 'c', /* default value string handle index */
897     };
898     std::vector<uint8_t> integerEntry{
899         2,  0,                   /* attr handle */
900         3,                       /* attr type */
901         10, 0, 0, 0, 0, 0, 0, 0, /* current value */
902     };
903 
904     Table srcTable;
905     buildTable(srcTable, enumEntry, stringEntry, integerEntry);
906 
907     std::vector<uint8_t> stringEntry1{
908         1,   0,        /* attr handle */
909         1,             /* attr type */
910         3,   0,        /* current string length */
911         'd', 'e', 'f', /* default value string handle index */
912     };
913 
914     Table expectTable;
915     buildTable(expectTable, enumEntry, stringEntry1, integerEntry);
916     Table destTable(expectTable.size() + 10);
917     auto destLength = destTable.size();
918     auto rc = pldm_bios_table_attr_value_copy_and_update(
919         srcTable.data(), srcTable.size(), destTable.data(), &destLength,
920         stringEntry1.data(), stringEntry1.size());
921 
922     EXPECT_EQ(rc, PLDM_SUCCESS);
923     EXPECT_EQ(destLength, expectTable.size());
924     destTable.resize(destLength);
925     EXPECT_THAT(destTable, ElementsAreArray(expectTable));
926 
927     std::vector<uint8_t> stringEntry2{
928         1,   0,                  /* attr handle */
929         1,                       /* attr type */
930         5,   0,                  /* current string length */
931         'd', 'e', 'f', 'a', 'b', /* default value string handle index */
932     };
933     expectTable.resize(0);
934     buildTable(expectTable, enumEntry, stringEntry2, integerEntry);
935     destTable.resize(expectTable.size() + 10);
936     destLength = destTable.size();
937     rc = pldm_bios_table_attr_value_copy_and_update(
938         srcTable.data(), srcTable.size(), destTable.data(), &destLength,
939         stringEntry2.data(), stringEntry2.size());
940     EXPECT_EQ(rc, PLDM_SUCCESS);
941     EXPECT_EQ(destLength, expectTable.size());
942     destTable.resize(destLength);
943     EXPECT_THAT(destTable, ElementsAreArray(expectTable));
944 
945     std::vector<uint8_t> stringEntry3{
946         1,   0, /* attr handle */
947         1,      /* attr type */
948         1,   0, /* current string length */
949         'd',    /* default value string handle index */
950     };
951     expectTable.resize(0);
952     buildTable(expectTable, enumEntry, stringEntry3, integerEntry);
953     destTable.resize(expectTable.size() + 10);
954     destLength = destTable.size();
955     rc = pldm_bios_table_attr_value_copy_and_update(
956         srcTable.data(), srcTable.size(), destTable.data(), &destLength,
957         stringEntry3.data(), stringEntry3.size());
958     EXPECT_EQ(rc, PLDM_SUCCESS);
959     EXPECT_EQ(destLength, expectTable.size());
960     destTable.resize(destLength);
961     EXPECT_THAT(destTable, ElementsAreArray(expectTable));
962 
963     stringEntry3[2] = PLDM_BIOS_INTEGER; // set attribute type to integer
964     rc = pldm_bios_table_attr_value_copy_and_update(
965         srcTable.data(), srcTable.size(), destTable.data(), &destLength,
966         stringEntry3.data(), stringEntry3.size());
967     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
968     stringEntry3[2] = PLDM_BIOS_STRING; // set attribute type to string
969 
970     destTable.resize(expectTable.size() - 1);
971     destLength = destTable.size();
972     rc = pldm_bios_table_attr_value_copy_and_update(
973         srcTable.data(), srcTable.size(), destTable.data(), &destLength,
974         stringEntry3.data(), stringEntry3.size());
975     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
976 }
977 
978 TEST(StringTable, EntryEncodeTest)
979 {
980     std::vector<uint8_t> stringEntry{
981         0,   0,                            /* string handle*/
982         7,   0,                            /* string length */
983         'A', 'l', 'l', 'o', 'w', 'e', 'd', /* string */
984     };
985 
986     const char* str = "Allowed";
987     auto str_length = std::strlen(str);
988     auto encodeLength = pldm_bios_table_string_entry_encode_length(str_length);
989     EXPECT_EQ(encodeLength, stringEntry.size());
990 
991     std::vector<uint8_t> encodeEntry(encodeLength, 0);
992     ASSERT_EQ(pldm_bios_table_string_entry_encode(
993                   encodeEntry.data(), encodeEntry.size(), str, str_length),
994               PLDM_SUCCESS);
995     // set string handle = 0
996     encodeEntry[0] = 0;
997     encodeEntry[1] = 0;
998 
999     EXPECT_EQ(stringEntry, encodeEntry);
1000 
1001     EXPECT_NE(pldm_bios_table_string_entry_encode(
1002                   encodeEntry.data(), encodeEntry.size() - 1, str, str_length),
1003               PLDM_SUCCESS);
1004     auto rc = pldm_bios_table_string_entry_encode(
1005         encodeEntry.data(), encodeEntry.size() - 1, str, str_length);
1006     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
1007 }
1008 
1009 TEST(StringTable, EntryDecodeTest)
1010 {
1011     std::vector<uint8_t> stringEntry{
1012         4,   0,                            /* string handle*/
1013         7,   0,                            /* string length */
1014         'A', 'l', 'l', 'o', 'w', 'e', 'd', /* string */
1015     };
1016     auto entry = reinterpret_cast<struct pldm_bios_string_table_entry*>(
1017         stringEntry.data());
1018     auto handle = pldm_bios_table_string_entry_decode_handle(entry);
1019     EXPECT_EQ(handle, 4);
1020     auto strLength = pldm_bios_table_string_entry_decode_string_length(entry);
1021     EXPECT_EQ(strLength, 7);
1022 
1023     std::vector<char> buffer(strLength + 1, 0);
1024     pldm_bios_table_string_entry_decode_string(entry, buffer.data(),
1025                                                buffer.size());
1026     EXPECT_EQ(strlen(buffer.data()), strLength);
1027     EXPECT_EQ(std::strcmp("Allowed", buffer.data()), 0);
1028     EXPECT_EQ(pldm_bios_table_string_entry_decode_string(
1029                   entry, buffer.data(), 2 + 1 /* sizeof '\0'*/),
1030               PLDM_SUCCESS);
1031     EXPECT_EQ(strlen(buffer.data()), 2);
1032     EXPECT_EQ(std::strcmp("Al", buffer.data()), 0);
1033 
1034     auto rc = pldm_bios_table_string_entry_decode_string(entry, buffer.data(),
1035                                                          buffer.size());
1036     EXPECT_EQ(rc, PLDM_SUCCESS);
1037     EXPECT_EQ(std::strcmp("Allowed", buffer.data()), 0);
1038 
1039     /* Ensure equivalence with the unchecked API */
1040     rc = pldm_bios_table_string_entry_decode_string(entry, buffer.data(),
1041                                                     2 + 1 /* sizeof '\0' */);
1042     EXPECT_EQ(rc, std::strcmp("Al", buffer.data()));
1043 }
1044 
1045 TEST(StringTable, IteratorTest)
1046 {
1047     std::vector<uint8_t> stringHello{
1048         0,   0,                  /* string handle*/
1049         5,   0,                  /* string length */
1050         'H', 'e', 'l', 'l', 'o', /* string */
1051     };
1052     std::vector<uint8_t> stringWorld{
1053         1,   0,                       /* string handle*/
1054         6,   0,                       /* string length */
1055         'W', 'o', 'r', 'l', 'd', '!', /* string */
1056     };
1057 
1058     Table table;
1059     buildTable(table, stringHello, stringWorld);
1060 
1061     auto iter = pldm_bios_table_iter_create(table.data(), table.size(),
1062                                             PLDM_BIOS_STRING_TABLE);
1063     auto entry = pldm_bios_table_iter_string_entry_value(iter);
1064     auto rc = std::memcmp(entry, stringHello.data(), stringHello.size());
1065     EXPECT_EQ(rc, 0);
1066     pldm_bios_table_iter_next(iter);
1067     entry = pldm_bios_table_iter_string_entry_value(iter);
1068     rc = std::memcmp(entry, stringWorld.data(), stringWorld.size());
1069     EXPECT_EQ(rc, 0);
1070     pldm_bios_table_iter_next(iter);
1071     EXPECT_TRUE(pldm_bios_table_iter_is_end(iter));
1072     pldm_bios_table_iter_free(iter);
1073 }
1074 
1075 TEST(StringTable, FindTest)
1076 {
1077     std::vector<uint8_t> stringHello{
1078         1,   0,                  /* string handle*/
1079         5,   0,                  /* string length */
1080         'H', 'e', 'l', 'l', 'o', /* string */
1081     };
1082     std::vector<uint8_t> stringWorld{
1083         2,   0,                       /* string handle*/
1084         6,   0,                       /* string length */
1085         'W', 'o', 'r', 'l', 'd', '!', /* string */
1086     };
1087     std::vector<uint8_t> stringHi{
1088         3,   0,   /* string handle*/
1089         2,   0,   /* string length */
1090         'H', 'i', /* string */
1091     };
1092 
1093     Table table;
1094     buildTable(table, stringHello, stringWorld, stringHi);
1095 
1096     auto entry = pldm_bios_table_string_find_by_string(table.data(),
1097                                                        table.size(), "World!");
1098     EXPECT_NE(entry, nullptr);
1099     auto handle = pldm_bios_table_string_entry_decode_handle(entry);
1100     EXPECT_EQ(handle, 2);
1101 
1102     entry = pldm_bios_table_string_find_by_string(table.data(), table.size(),
1103                                                   "Worl");
1104     EXPECT_EQ(entry, nullptr);
1105 
1106     entry =
1107         pldm_bios_table_string_find_by_handle(table.data(), table.size(), 3);
1108     EXPECT_NE(entry, nullptr);
1109     auto str_length = pldm_bios_table_string_entry_decode_string_length(entry);
1110     EXPECT_EQ(str_length, 2);
1111     std::vector<char> strBuf(str_length + 1, 0);
1112     auto rc = pldm_bios_table_string_entry_decode_string(entry, strBuf.data(),
1113                                                          strBuf.size());
1114     EXPECT_EQ(rc, PLDM_SUCCESS);
1115     EXPECT_EQ(std::strcmp("Hi", strBuf.data()), 0);
1116 
1117     entry =
1118         pldm_bios_table_string_find_by_handle(table.data(), table.size(), 4);
1119     EXPECT_EQ(entry, nullptr);
1120 }
1121 
1122 TEST(Iterator, DeathTest)
1123 {
1124 
1125     Table table(256, 0);
1126 
1127     /* first entry */
1128     auto attr_entry =
1129         reinterpret_cast<struct pldm_bios_attr_table_entry*>(table.data());
1130     auto iter = pldm_bios_table_iter_create(table.data(), table.size(),
1131                                             PLDM_BIOS_ATTR_TABLE);
1132     attr_entry->attr_type = PLDM_BIOS_PASSWORD;
1133 #ifndef NDEBUG
1134     EXPECT_DEATH(pldm_bios_table_iter_next(iter), "attr_table_entry != NULL");
1135 #endif
1136     pldm_bios_table_iter_free(iter);
1137 }
1138 
1139 TEST(PadAndChecksum, PadAndChecksum)
1140 {
1141     EXPECT_EQ(4u, pldm_bios_table_pad_checksum_size(0));
1142     EXPECT_EQ(7u, pldm_bios_table_pad_checksum_size(1));
1143     EXPECT_EQ(6u, pldm_bios_table_pad_checksum_size(2));
1144     EXPECT_EQ(5u, pldm_bios_table_pad_checksum_size(3));
1145     EXPECT_EQ(4u, pldm_bios_table_pad_checksum_size(4));
1146 
1147     // The table is borrowed from
1148     // https://github.com/openbmc/pldm/commit/69d3e7fb2d9935773f4fbf44326c33f3fc0a3c38
1149     // refer to the commit message
1150     Table attrValTable = {0x09, 0x00, 0x01, 0x02, 0x00, 0x65, 0x66};
1151     auto sizeWithoutPad = attrValTable.size();
1152     attrValTable.resize(sizeWithoutPad +
1153                         pldm_bios_table_pad_checksum_size(sizeWithoutPad));
1154     ASSERT_EQ(pldm_bios_table_append_pad_checksum(
1155                   attrValTable.data(), attrValTable.size(), &sizeWithoutPad),
1156               PLDM_SUCCESS);
1157     Table expectedTable = {0x09, 0x00, 0x01, 0x02, 0x00, 0x65,
1158                            0x66, 0x00, 0x6d, 0x81, 0x4a, 0xb6};
1159     EXPECT_EQ(attrValTable, expectedTable);
1160 }
1161 
1162 TEST(BIOSTableChecksum, testBIOSTableChecksum)
1163 {
1164     std::vector<uint8_t> stringTable{
1165         1,   0,                  /* string handle*/
1166         5,   0,                  /* string length */
1167         'T', 'a', 'b', 'l', 'e', /* string */
1168     };
1169 
1170     buildTable(stringTable);
1171 
1172     EXPECT_EQ(true,
1173               pldm_bios_table_checksum(stringTable.data(), stringTable.size()));
1174 }
1175