1 /**
2  * Copyright © 2018 Intel 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 <ipmid/api.hpp>
17 #include <ipmid/message.hpp>
18 
19 #include <gtest/gtest.h>
20 
TEST(Uints,Uint8)21 TEST(Uints, Uint8)
22 {
23     ipmi::SecureBuffer i = {0x04};
24     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
25     uint8_t v;
26     // check that the number of bytes matches
27     ASSERT_EQ(p.unpack(v), 0);
28     // check that the payload was fully unpacked
29     ASSERT_TRUE(p.fullyUnpacked());
30     uint8_t k = 0x04;
31     // check that the bytes were correctly unpacked (LSB first)
32     ASSERT_EQ(v, k);
33 }
34 
TEST(Uints,Uint8TooManyBytes)35 TEST(Uints, Uint8TooManyBytes)
36 {
37     ipmi::SecureBuffer i = {0x04, 0x86};
38     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
39     uint8_t v;
40     // check that the number of bytes matches
41     ASSERT_EQ(p.unpack(v), 0);
42     // check that the payload was not fully unpacked
43     ASSERT_FALSE(p.fullyUnpacked());
44     uint8_t k = 0x04;
45     // check that the bytes were correctly unpacked (LSB first)
46     ASSERT_EQ(v, k);
47 }
48 
TEST(Uints,Uint8InsufficientBytes)49 TEST(Uints, Uint8InsufficientBytes)
50 {
51     ipmi::SecureBuffer i = {};
52     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
53     uint8_t v = 0;
54     // check that the number of bytes matches
55     ASSERT_NE(p.unpack(v), 0);
56     // check that the payload was not fully unpacked (comprehends unpack errors)
57     ASSERT_FALSE(p.fullyUnpacked());
58     // check that v is zero
59     ASSERT_EQ(v, 0);
60 }
61 
TEST(Uints,Uint16)62 TEST(Uints, Uint16)
63 {
64     ipmi::SecureBuffer i = {0x04, 0x86};
65     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
66     uint16_t v;
67     // check that the number of bytes matches
68     ASSERT_EQ(p.unpack(v), 0);
69     // check that the payload was fully unpacked
70     ASSERT_TRUE(p.fullyUnpacked());
71     uint16_t k = 0x8604;
72     // check that the bytes were correctly unpacked (LSB first)
73     ASSERT_EQ(v, k);
74 }
75 
TEST(Uints,Uint16TooManyBytes)76 TEST(Uints, Uint16TooManyBytes)
77 {
78     ipmi::SecureBuffer i = {0x04, 0x86, 0x00};
79     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
80     uint16_t v;
81     // check that the number of bytes matches
82     ASSERT_EQ(p.unpack(v), 0);
83     // check that the payload was not fully unpacked
84     ASSERT_FALSE(p.fullyUnpacked());
85     uint16_t k = 0x8604;
86     // check that the bytes were correctly unpacked (LSB first)
87     ASSERT_EQ(v, k);
88 }
89 
TEST(Uints,Uint16InsufficientBytes)90 TEST(Uints, Uint16InsufficientBytes)
91 {
92     ipmi::SecureBuffer i = {0x04};
93     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
94     uint16_t v = 0;
95     // check that the number of bytes matches
96     ASSERT_NE(p.unpack(v), 0);
97     // check that the payload was not fully unpacked (comprehends unpack errors)
98     ASSERT_FALSE(p.fullyUnpacked());
99     // check that v is zero
100     ASSERT_EQ(v, 0);
101 }
102 
TEST(Uints,Uint32)103 TEST(Uints, Uint32)
104 {
105     ipmi::SecureBuffer i = {0x04, 0x86, 0x00, 0x02};
106     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
107     uint32_t v;
108     // check that the number of bytes matches
109     ASSERT_EQ(p.unpack(v), 0);
110     // check that the payload was fully unpacked
111     ASSERT_TRUE(p.fullyUnpacked());
112     uint32_t k = 0x02008604;
113     // check that the bytes were correctly unpacked (LSB first)
114     ASSERT_EQ(v, k);
115 }
116 
TEST(Uints,Uint32TooManyBytes)117 TEST(Uints, Uint32TooManyBytes)
118 {
119     ipmi::SecureBuffer i = {0x04, 0x86, 0x00, 0x02, 0x44};
120     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
121     uint32_t v;
122     // check that the number of bytes matches
123     ASSERT_EQ(p.unpack(v), 0);
124     // check that the payload was not fully unpacked
125     ASSERT_FALSE(p.fullyUnpacked());
126     uint32_t k = 0x02008604;
127     // check that the bytes were correctly unpacked (LSB first)
128     ASSERT_EQ(v, k);
129 }
130 
TEST(Uints,Uint32InsufficientBytes)131 TEST(Uints, Uint32InsufficientBytes)
132 {
133     ipmi::SecureBuffer i = {0x04, 0x86, 0x00};
134     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
135     uint32_t v = 0;
136     // check that the number of bytes matches
137     ASSERT_NE(p.unpack(v), 0);
138     // check that the payload was not fully unpacked (comprehends unpack errors)
139     ASSERT_FALSE(p.fullyUnpacked());
140     // check that v is zero
141     ASSERT_EQ(v, 0);
142 }
143 
TEST(Uints,Uint64)144 TEST(Uints, Uint64)
145 {
146     ipmi::SecureBuffer i = {0x04, 0x86, 0x00, 0x02, 0x44, 0x33, 0x22, 0x11};
147     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
148     uint64_t v;
149     // check that the number of bytes matches
150     ASSERT_EQ(p.unpack(v), 0);
151     // check that the payload was fully unpacked
152     ASSERT_TRUE(p.fullyUnpacked());
153     uint64_t k = 0x1122334402008604ull;
154     // check that the bytes were correctly unpacked (LSB first)
155     ASSERT_EQ(v, k);
156 }
157 
TEST(Uints,Uint64TooManyBytes)158 TEST(Uints, Uint64TooManyBytes)
159 {
160     ipmi::SecureBuffer i = {0x04, 0x86, 0x00, 0x02, 0x44,
161                             0x33, 0x22, 0x11, 0x55};
162     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
163     uint64_t v;
164     // check that the number of bytes matches
165     ASSERT_EQ(p.unpack(v), 0);
166     // check that the payload was not fully unpacked
167     ASSERT_FALSE(p.fullyUnpacked());
168     uint64_t k = 0x1122334402008604ull;
169     // check that the bytes were correctly unpacked (LSB first)
170     ASSERT_EQ(v, k);
171 }
172 
TEST(Uints,Uint64InsufficientBytes)173 TEST(Uints, Uint64InsufficientBytes)
174 {
175     ipmi::SecureBuffer i = {0x04, 0x86, 0x00, 0x02, 0x44, 0x33, 0x22};
176     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
177     uint64_t v = 0;
178     // check that the number of bytes matches
179     ASSERT_NE(p.unpack(v), 0);
180     // check that the payload was not fully unpacked (comprehends unpack errors)
181     ASSERT_FALSE(p.fullyUnpacked());
182     // check that v is zero
183     ASSERT_EQ(v, 0);
184 }
185 
TEST(Uints,Uint24)186 TEST(Uints, Uint24)
187 {
188     ipmi::SecureBuffer i = {0x58, 0x23, 0x11};
189     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
190     uint24_t v;
191     // check that the number of bytes matches
192     ASSERT_EQ(p.unpack(v), 0);
193     // check that the payload was fully unpacked
194     ASSERT_TRUE(p.fullyUnpacked());
195     uint24_t k = 0x112358;
196     // check that the bytes were correctly unpacked (LSB first)
197     ASSERT_EQ(v, k);
198 }
199 
TEST(FixedInts,Uint24TooManyBytes)200 TEST(FixedInts, Uint24TooManyBytes)
201 {
202     ipmi::SecureBuffer i = {0x58, 0x23, 0x11, 0x00};
203     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
204     uint24_t v;
205     // check that the number of bytes matches
206     ASSERT_EQ(p.unpack(v), 0);
207     // check that the payload was not fully unpacked
208     ASSERT_FALSE(p.fullyUnpacked());
209     uint24_t k = 0x112358;
210     // check that the bytes were correctly unpacked (LSB first)
211     ASSERT_EQ(v, k);
212 }
213 
TEST(FixedInts,Uint24InsufficientBytes)214 TEST(FixedInts, Uint24InsufficientBytes)
215 {
216     ipmi::SecureBuffer i = {0x58, 0x23};
217     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
218     uint24_t v = 0;
219     // check that the number of bytes matches
220     ASSERT_NE(p.unpack(v), 0);
221     // check that the payload was not fully unpacked (comprehends unpack errors)
222     ASSERT_FALSE(p.fullyUnpacked());
223     // check that v is zero
224     ASSERT_EQ(v, 0);
225 }
226 
TEST(FixedInts,Uint3Uint5)227 TEST(FixedInts, Uint3Uint5)
228 {
229     // individual bytes are unpacked low-order-bits first
230     // v1 will use [2:0], v2 will use [7:3]
231     ipmi::SecureBuffer i = {0xc9};
232     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
233     uint3_t v1;
234     uint5_t v2;
235     // check that the number of bytes matches
236     ASSERT_EQ(p.unpack(v1, v2), 0);
237     // check that the payload was fully unpacked
238     ASSERT_TRUE(p.fullyUnpacked());
239     uint3_t k1 = 0x1;
240     uint5_t k2 = 0x19;
241     // check that the bytes were correctly unpacked (LSB first)
242     ASSERT_EQ(v1, k1);
243     ASSERT_EQ(v2, k2);
244 }
245 
TEST(FixedInts,Uint3Uint4TooManyBits)246 TEST(FixedInts, Uint3Uint4TooManyBits)
247 {
248     // high order bit should not get unpacked
249     ipmi::SecureBuffer i = {0xc9};
250     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
251     uint3_t v1;
252     uint4_t v2;
253     // check that the number of bytes matches
254     ASSERT_EQ(p.unpack(v1, v2), 0);
255     // check that the payload was not fully unpacked
256     ASSERT_FALSE(p.fullyUnpacked());
257     uint3_t k1 = 0x1;
258     uint4_t k2 = 0x9;
259     // check that the bytes were correctly unpacked (LSB first)
260     ASSERT_EQ(v1, k1);
261     ASSERT_EQ(v2, k2);
262 }
263 
TEST(FixedInts,Uint3Uint6InsufficientBits)264 TEST(FixedInts, Uint3Uint6InsufficientBits)
265 {
266     // insufficient bits to unpack v2
267     ipmi::SecureBuffer i = {0xc9};
268     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
269     uint3_t v1;
270     uint6_t v2;
271     // check that the number of bytes matches
272     ASSERT_NE(p.unpack(v1, v2), 0);
273     // check that the payload was not fully unpacked (comprehends unpack errors)
274     ASSERT_FALSE(p.fullyUnpacked());
275     uint3_t k1 = 0x1;
276     // check that the bytes were correctly unpacked (LSB first)
277     ASSERT_EQ(v1, k1);
278     // check that v2 is zero
279     ASSERT_EQ(v2, 0);
280 }
281 
TEST(Bools,Boolx8)282 TEST(Bools, Boolx8)
283 {
284     // individual bytes are unpacked low-order-bits first
285     // [v8, v7, v6, v5, v4, v3, v2, v1]
286     ipmi::SecureBuffer i = {0xc9};
287     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
288     bool v8, v7, v6, v5;
289     bool v4, v3, v2, v1;
290     // check that the number of bytes matches
291     ASSERT_EQ(p.unpack(v1, v2, v3, v4, v5, v6, v7, v8), 0);
292     // check that the payload was fully unpacked
293     ASSERT_TRUE(p.fullyUnpacked());
294     // check that the bytes were correctly unpacked (LSB first)
295     bool k8 = true, k7 = true, k6 = false, k5 = false;
296     bool k4 = true, k3 = false, k2 = false, k1 = true;
297     ASSERT_EQ(v1, k1);
298     ASSERT_EQ(v2, k2);
299     ASSERT_EQ(v3, k3);
300     ASSERT_EQ(v4, k4);
301     ASSERT_EQ(v5, k5);
302     ASSERT_EQ(v6, k6);
303     ASSERT_EQ(v7, k7);
304     ASSERT_EQ(v8, k8);
305 }
306 
TEST(Bools,Boolx8TooManyBits)307 TEST(Bools, Boolx8TooManyBits)
308 {
309     // high order bit should not get unpacked
310     // individual bytes are unpacked low-order-bits first
311     // [v7, v6, v5, v4, v3, v2, v1]
312     ipmi::SecureBuffer i = {0xc9};
313     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
314     bool v7, v6, v5;
315     bool v4, v3, v2, v1;
316     // check that the number of bytes matches
317     ASSERT_EQ(p.unpack(v1, v2, v3, v4, v5, v6, v7), 0);
318     // check that the payload was not fully unpacked
319     ASSERT_FALSE(p.fullyUnpacked());
320     // check that the bytes were correctly unpacked (LSB first)
321     bool k7 = true, k6 = false, k5 = false;
322     bool k4 = true, k3 = false, k2 = false, k1 = true;
323     ASSERT_EQ(v1, k1);
324     ASSERT_EQ(v2, k2);
325     ASSERT_EQ(v3, k3);
326     ASSERT_EQ(v4, k4);
327     ASSERT_EQ(v5, k5);
328     ASSERT_EQ(v6, k6);
329     ASSERT_EQ(v7, k7);
330 }
331 
TEST(Bools,Boolx8InsufficientBits)332 TEST(Bools, Boolx8InsufficientBits)
333 {
334     // individual bytes are unpacked low-order-bits first
335     // [v8, v7, v6, v5, v4, v3, v2, v1]
336     ipmi::SecureBuffer i = {0xc9};
337     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
338     bool v9;
339     bool v8, v7, v6, v5;
340     bool v4, v3, v2, v1;
341     // check that the number of bytes matches
342     ASSERT_NE(p.unpack(v1, v2, v3, v4, v5, v6, v7, v8, v9), 0);
343     // check that the payload was not fully unpacked (comprehends unpack errors)
344     ASSERT_FALSE(p.fullyUnpacked());
345     // check that the bytes were correctly unpacked (LSB first)
346     bool k8 = true, k7 = true, k6 = false, k5 = false;
347     bool k4 = true, k3 = false, k2 = false, k1 = true;
348     ASSERT_EQ(v1, k1);
349     ASSERT_EQ(v2, k2);
350     ASSERT_EQ(v3, k3);
351     ASSERT_EQ(v4, k4);
352     ASSERT_EQ(v5, k5);
353     ASSERT_EQ(v6, k6);
354     ASSERT_EQ(v7, k7);
355     ASSERT_EQ(v8, k8);
356 }
357 
TEST(Bitsets,Bitset8)358 TEST(Bitsets, Bitset8)
359 {
360     // individual bytes are unpacked low-order-bits first
361     // a bitset for 8 bits fills the full byte
362     ipmi::SecureBuffer i = {0xc9};
363     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
364     std::bitset<8> v;
365     // check that the number of bytes matches
366     ASSERT_EQ(p.unpack(v), 0);
367     // check that the payload was fully unpacked
368     ASSERT_TRUE(p.fullyUnpacked());
369     std::bitset<8> k(0xc9);
370     // check that the bytes were correctly unpacked (LSB first)
371     ASSERT_EQ(v, k);
372 }
373 
TEST(Bitsets,Bitset7TooManyBits)374 TEST(Bitsets, Bitset7TooManyBits)
375 {
376     // individual bytes are unpacked low-order-bits first
377     // a bitset for 8 bits fills the full byte
378     ipmi::SecureBuffer i = {0xc9};
379     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
380     std::bitset<7> v;
381     // check that the number of bytes matches
382     ASSERT_EQ(p.unpack(v), 0);
383     // check that the payload was not fully unpacked
384     ASSERT_FALSE(p.fullyUnpacked());
385     std::bitset<7> k(0x49);
386     // check that the bytes were correctly unpacked (LSB first)
387     ASSERT_EQ(v, k);
388 }
389 
TEST(Bitsets,Bitset9InsufficientBits)390 TEST(Bitsets, Bitset9InsufficientBits)
391 {
392     // individual bytes are unpacked low-order-bits first
393     // a bitset for 8 bits fills the full byte
394     ipmi::SecureBuffer i = {0xc9};
395     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
396     std::bitset<9> v;
397     // check that the number of bytes matches
398     ASSERT_NE(p.unpack(v), 0);
399     // check that the payload was not fully unpacked (comprehends unpack errors)
400     ASSERT_FALSE(p.fullyUnpacked());
401     std::bitset<9> k(0);
402     // check that the bytes were correctly unpacked (LSB first)
403     ASSERT_EQ(v, k);
404 }
405 
TEST(Bitsets,Bitset3Bitset5)406 TEST(Bitsets, Bitset3Bitset5)
407 {
408     // individual bytes are unpacked low-order-bits first
409     // v1 will use [2:0], v2 will use [7:3]
410     ipmi::SecureBuffer i = {0xc9};
411     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
412     std::bitset<3> v1;
413     std::bitset<5> v2;
414     // check that the number of bytes matches
415     ASSERT_EQ(p.unpack(v1, v2), 0);
416     // check that the payload was fully unpacked
417     ASSERT_TRUE(p.fullyUnpacked());
418     std::bitset<3> k1(0x1);
419     std::bitset<5> k2(0x19);
420     // check that the bytes were correctly unpacked (LSB first)
421     ASSERT_EQ(v1, k1);
422     ASSERT_EQ(v2, k2);
423 }
424 
TEST(Bitsets,Bitset3Bitset4TooManyBits)425 TEST(Bitsets, Bitset3Bitset4TooManyBits)
426 {
427     // high order bit should not get unpacked
428     ipmi::SecureBuffer i = {0xc9};
429     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
430     std::bitset<3> v1;
431     std::bitset<4> v2;
432     // check that the number of bytes matches
433     ASSERT_EQ(p.unpack(v1, v2), 0);
434     // check that the payload was not fully unpacked
435     ASSERT_FALSE(p.fullyUnpacked());
436     std::bitset<3> k1 = 0x1;
437     std::bitset<4> k2 = 0x9;
438     // check that the bytes were correctly unpacked (LSB first)
439     ASSERT_EQ(v1, k1);
440     ASSERT_EQ(v2, k2);
441 }
442 
TEST(Bitsets,Bitset3Bitset6InsufficientBits)443 TEST(Bitsets, Bitset3Bitset6InsufficientBits)
444 {
445     // insufficient bits to unpack v2
446     ipmi::SecureBuffer i = {0xc9};
447     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
448     std::bitset<3> v1;
449     std::bitset<6> v2;
450     // check that the number of bytes matches
451     ASSERT_NE(p.unpack(v1, v2), 0);
452     // check that the payload was not fully unpacked (comprehends unpack errors)
453     ASSERT_FALSE(p.fullyUnpacked());
454     std::bitset<3> k1 = 0x1;
455     // check that the bytes were correctly unpacked (LSB first)
456     ASSERT_EQ(v1, k1);
457     // check that v2 is zero
458     ASSERT_EQ(v2, 0);
459 }
460 
TEST(Bitsets,Bitset32)461 TEST(Bitsets, Bitset32)
462 {
463     // individual bytes are unpacked low-order-bits first
464     // v1 will use 4 bytes, but in LSByte first order
465     // v1[7:0] v1[15:9] v1[23:16] v1[31:24]
466     ipmi::SecureBuffer i = {0xb4, 0x86, 0x91, 0xc2};
467     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
468     std::bitset<32> v;
469     // check that the number of bytes matches
470     ASSERT_EQ(p.unpack(v), 0);
471     // check that the payload was fully unpacked
472     ASSERT_TRUE(p.fullyUnpacked());
473     std::bitset<32> k(0xc29186b4);
474     // check that the bytes were correctly unpacked (LSB first)
475     ASSERT_EQ(v, k);
476 }
477 
TEST(Bitsets,Bitset31TooManyBits)478 TEST(Bitsets, Bitset31TooManyBits)
479 {
480     // high order bit should not get unpacked
481     ipmi::SecureBuffer i = {0xb4, 0x86, 0x91, 0xc2};
482     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
483     std::bitset<31> v;
484     // check that the number of bytes matches
485     ASSERT_EQ(p.unpack(v), 0);
486     // check that the payload was not fully unpacked
487     ASSERT_FALSE(p.fullyUnpacked());
488     std::bitset<31> k(0x429186b4);
489     // check that the bytes were correctly unpacked (LSB first)
490     ASSERT_EQ(v, k);
491 }
492 
TEST(Bitsets,Bitset33InsufficientBits)493 TEST(Bitsets, Bitset33InsufficientBits)
494 {
495     // insufficient bits to unpack v2
496     ipmi::SecureBuffer i = {0xb4, 0x86, 0x91, 0xc2};
497     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
498     std::bitset<33> v;
499     // check that the number of bytes matches
500     ASSERT_NE(p.unpack(v), 0);
501     // check that the payload was not fully unpacked (comprehends unpack errors)
502     ASSERT_FALSE(p.fullyUnpacked());
503     // check that v is zero
504     ASSERT_EQ(v, 0);
505 }
506 
TEST(Arrays,Array4xUint8)507 TEST(Arrays, Array4xUint8)
508 {
509     // an array of bytes will be read verbatim, low-order element first
510     ipmi::SecureBuffer i = {0x02, 0x00, 0x86, 0x04};
511     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
512     std::array<uint8_t, 4> v;
513     // check that the number of bytes matches
514     ASSERT_EQ(p.unpack(v), 0);
515     // check that the payload was fully unpacked
516     ASSERT_TRUE(p.fullyUnpacked());
517     std::array<uint8_t, 4> k = {{0x02, 0x00, 0x86, 0x04}};
518     // check that the bytes were correctly unpacked (in byte order)
519     ASSERT_EQ(v, k);
520 }
521 
TEST(Arrays,Array4xUint8TooManyBytes)522 TEST(Arrays, Array4xUint8TooManyBytes)
523 {
524     // last byte should not get unpacked
525     // an array of bytes will be read verbatim, low-order element first
526     ipmi::SecureBuffer i = {0x02, 0x00, 0x86, 0x04, 0x22};
527     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
528     std::array<uint8_t, 4> v;
529     // check that the number of bytes matches
530     ASSERT_EQ(p.unpack(v), 0);
531     // check that the payload was not fully unpacked
532     ASSERT_FALSE(p.fullyUnpacked());
533     std::array<uint8_t, 4> k = {{0x02, 0x00, 0x86, 0x04}};
534     // check that the bytes were correctly unpacked (in byte order)
535     ASSERT_EQ(v, k);
536 }
537 
TEST(Arrays,Array4xUint8InsufficientBytes)538 TEST(Arrays, Array4xUint8InsufficientBytes)
539 {
540     // last byte should not get unpacked
541     // an array of bytes will be read verbatim, low-order element first
542     ipmi::SecureBuffer i = {0x02, 0x00, 0x86};
543     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
544     std::array<uint8_t, 4> v;
545     // check that the number of bytes matches
546     ASSERT_NE(p.unpack(v), 0);
547     // check that the payload was not fully unpacked
548     ASSERT_FALSE(p.fullyUnpacked());
549     // arrays of uint8_t will be unpacked all at once
550     // so nothing will get unpacked
551     std::array<uint8_t, 4> k = {{0, 0, 0, 0}};
552     // check that the bytes were correctly unpacked (in byte order)
553     ASSERT_EQ(v, k);
554 }
555 
TEST(Arrays,Array4xUint32)556 TEST(Arrays, Array4xUint32)
557 {
558     // an array of multi-byte values will be unpacked in order low-order
559     // element first, each multi-byte element in LSByte order
560     // v[0][7:0] v[0][15:9] v[0][23:16] v[0][31:24]
561     // v[1][7:0] v[1][15:9] v[1][23:16] v[1][31:24]
562     // v[2][7:0] v[2][15:9] v[2][23:16] v[2][31:24]
563     // v[3][7:0] v[3][15:9] v[3][23:16] v[3][31:24]
564     ipmi::SecureBuffer i = {0x44, 0x33, 0x22, 0x11, 0x88, 0x66, 0x44, 0x22,
565                             0x99, 0x77, 0x55, 0x33, 0x78, 0x56, 0x34, 0x12};
566     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
567     std::array<uint32_t, 4> v;
568     // check that the number of bytes matches
569     ASSERT_EQ(p.unpack(v), 0);
570     // check that the payload was fully unpacked
571     ASSERT_TRUE(p.fullyUnpacked());
572     std::array<uint32_t, 4> k = {
573         {0x11223344, 0x22446688, 0x33557799, 0x12345678}};
574     // check that the bytes were correctly unpacked (in byte order)
575     ASSERT_EQ(v, k);
576 }
577 
TEST(Arrays,Array4xUint32TooManyBytes)578 TEST(Arrays, Array4xUint32TooManyBytes)
579 {
580     // last byte should not get unpacked
581     // an array of multi-byte values will be unpacked in order low-order
582     // element first, each multi-byte element in LSByte order
583     // v[0][7:0] v[0][15:9] v[0][23:16] v[0][31:24]
584     // v[1][7:0] v[1][15:9] v[1][23:16] v[1][31:24]
585     // v[2][7:0] v[2][15:9] v[2][23:16] v[2][31:24]
586     // v[3][7:0] v[3][15:9] v[3][23:16] v[3][31:24]
587     ipmi::SecureBuffer i = {0x44, 0x33, 0x22, 0x11, 0x88, 0x66,
588                             0x44, 0x22, 0x99, 0x77, 0x55, 0x33,
589                             0x78, 0x56, 0x34, 0x12, 0xaa};
590     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
591     std::array<uint32_t, 4> v;
592     // check that the number of bytes matches
593     ASSERT_EQ(p.unpack(v), 0);
594     // check that the payload was not fully unpacked
595     ASSERT_FALSE(p.fullyUnpacked());
596     std::array<uint32_t, 4> k = {
597         {0x11223344, 0x22446688, 0x33557799, 0x12345678}};
598     // check that the bytes were correctly unpacked (in byte order)
599     ASSERT_EQ(v, k);
600 }
601 
TEST(Arrays,Array4xUint32InsufficientBytes)602 TEST(Arrays, Array4xUint32InsufficientBytes)
603 {
604     // last value should not get unpacked
605     // an array of multi-byte values will be unpacked in order low-order
606     // element first, each multi-byte element in LSByte order
607     // v[0][7:0] v[0][15:9] v[0][23:16] v[0][31:24]
608     // v[1][7:0] v[1][15:9] v[1][23:16] v[1][31:24]
609     // v[2][7:0] v[2][15:9] v[2][23:16] v[2][31:24]
610     // v[3][7:0] v[3][15:9] v[3][23:16] v[3][31:24]
611     ipmi::SecureBuffer i = {0x44, 0x33, 0x22, 0x11, 0x88, 0x66, 0x44, 0x22,
612                             0x99, 0x77, 0x55, 0x33, 0x78, 0x56, 0x34};
613     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
614     std::array<uint32_t, 4> v;
615     // check that the number of bytes matches
616     ASSERT_NE(p.unpack(v), 0);
617     // check that the payload was not fully unpacked
618     ASSERT_FALSE(p.fullyUnpacked());
619     // arrays of uint32_t will be unpacked in a way that looks atomic
620     std::array<uint32_t, 4> k = {{0, 0, 0, 0}};
621     // check that the bytes were correctly unpacked (in byte order)
622     ASSERT_EQ(v, k);
623 }
624 
TEST(Vectors,VectorUint32)625 TEST(Vectors, VectorUint32)
626 {
627     // a vector of multi-byte values will be unpacked in order low-order
628     // element first, each multi-byte element in LSByte order
629     // v[0][7:0] v[0][15:9] v[0][23:16] v[0][31:24]
630     // v[1][7:0] v[1][15:9] v[1][23:16] v[1][31:24]
631     // v[2][7:0] v[2][15:9] v[2][23:16] v[2][31:24]
632     // v[3][7:0] v[3][15:9] v[3][23:16] v[3][31:24]
633     ipmi::SecureBuffer i = {0x44, 0x33, 0x22, 0x11, 0x88, 0x66, 0x44, 0x22,
634                             0x99, 0x77, 0x55, 0x33, 0x78, 0x56, 0x34, 0x12};
635     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
636     std::vector<uint32_t> v;
637     // check that the number of bytes matches
638     ASSERT_EQ(p.unpack(v), 0);
639     // check that the payload was fully unpacked
640     ASSERT_TRUE(p.fullyUnpacked());
641     std::vector<uint32_t> k = {0x11223344, 0x22446688, 0x33557799, 0x12345678};
642     // check that the bytes were correctly unpacked (in byte order)
643     ASSERT_EQ(v, k);
644 }
645 
646 // combination of TooManyBytes and InsufficientBytes because
647 // vectors will attempt to unpack full <T>s until the end of the input
TEST(Vectors,VectorUint32NonIntegralBytes)648 TEST(Vectors, VectorUint32NonIntegralBytes)
649 {
650     // last value should not get unpacked
651     // a vector of multi-byte values will be unpacked in order low-order
652     // element first, each multi-byte element in LSByte order,
653     // and will attempt to consume all bytes remaining
654     // v[0][7:0] v[0][15:9] v[0][23:16] v[0][31:24]
655     // v[1][7:0] v[1][15:9] v[1][23:16] v[1][31:24]
656     // v[2][7:0] v[2][15:9] v[2][23:16] v[2][31:24]
657     // v[3][7:0] v[3][15:9] v[3][23:16] v[3][31:24]
658     ipmi::SecureBuffer i = {0x44, 0x33, 0x22, 0x11, 0x88, 0x66, 0x44, 0x22,
659                             0x99, 0x77, 0x55, 0x33, 0x78, 0x56, 0x34};
660     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
661     std::vector<uint32_t> v;
662     // check that the vector unpacks successfully
663     ASSERT_EQ(p.unpack(v), 0);
664     // check that the payload was not fully unpacked
665     ASSERT_FALSE(p.fullyUnpacked());
666     // arrays of uint32_t will be unpacked one at a time, so the
667     // last entry should not get unpacked properly
668     std::vector<uint32_t> k = {0x11223344, 0x22446688, 0x33557799};
669     // check that the bytes were correctly unpacked (in byte order)
670     ASSERT_EQ(v, k);
671 }
672 
TEST(Vectors,VectorUint8)673 TEST(Vectors, VectorUint8)
674 {
675     // a vector of bytes will be unpacked verbatim, low-order element first
676     ipmi::SecureBuffer i = {0x02, 0x00, 0x86, 0x04};
677     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
678     std::vector<uint8_t> v;
679     // check that the number of bytes matches
680     ASSERT_EQ(p.unpack(v), 0);
681     // check that the payload was fully unpacked
682     ASSERT_TRUE(p.fullyUnpacked());
683     std::vector<uint8_t> k = {0x02, 0x00, 0x86, 0x04};
684     // check that the bytes were correctly unpacked (in byte order)
685     ASSERT_EQ(v, k);
686 }
687 
TEST(Vectors,VectorEmptyOk)688 TEST(Vectors, VectorEmptyOk)
689 {
690     // an empty input vector to show that unpacking elements is okay
691     ipmi::SecureBuffer i{};
692     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
693     std::vector<uint32_t> v;
694     // check that the number of bytes matches
695     ASSERT_EQ(p.unpack(v), 0);
696     // check that the payload was fully unpacked
697     ASSERT_TRUE(p.fullyUnpacked());
698     std::vector<uint32_t> k{};
699     // check that the unpacked vector is empty as expected
700     ASSERT_EQ(v, k);
701 }
702 
TEST(Vectors,VectorOfTuplesOk)703 TEST(Vectors, VectorOfTuplesOk)
704 {
705     // a vector of bytes will be unpacked verbatim, low-order element first
706     ipmi::SecureBuffer i = {0x02, 0x00, 0x86, 0x04};
707     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
708     std::vector<std::tuple<uint8_t, uint8_t>> v;
709     // check that the number of bytes matches
710     ASSERT_EQ(p.unpack(v), 0);
711     // check that the payload was fully unpacked
712     ASSERT_TRUE(p.fullyUnpacked());
713     std::vector<std::tuple<uint8_t, uint8_t>> k = {{0x02, 0x00}, {0x86, 0x04}};
714     // check that the bytes were correctly unpacked (in byte order)
715     ASSERT_EQ(v, k);
716 }
717 
TEST(Vectors,VectorOfTuplesInsufficientBytes)718 TEST(Vectors, VectorOfTuplesInsufficientBytes)
719 {
720     // a vector of bytes will be unpacked verbatim, low-order element first
721     ipmi::SecureBuffer i = {0x02, 0x00, 0x86, 0x04, 0xb4};
722     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
723     std::vector<std::tuple<uint8_t, uint8_t>> v;
724     // check that the number of bytes matches
725     ASSERT_EQ(p.unpack(v), 0);
726     // check that the payload was not fully unpacked
727     ASSERT_FALSE(p.fullyUnpacked());
728     std::vector<std::tuple<uint8_t, uint8_t>> k = {{0x02, 0x00}, {0x86, 0x04}};
729     // check that the bytes were correctly unpacked (in byte order)
730     ASSERT_EQ(v, k);
731 }
732 
733 // Cannot test TooManyBytes or InsufficientBytes for vector<uint8_t>
734 // because it will always unpack whatever bytes are remaining
735 // TEST(Vectors, VectorUint8TooManyBytes) {}
736 // TEST(Vectors, VectorUint8InsufficientBytes) {}
737 
TEST(UnpackAdvanced,OptionalOk)738 TEST(UnpackAdvanced, OptionalOk)
739 {
740     // a vector of bytes will be unpacked verbatim, low-order element first
741     ipmi::SecureBuffer i = {0xbe, 0x02, 0x00, 0x86, 0x04};
742     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
743     std::optional<std::tuple<uint8_t, uint32_t>> v;
744     // check that the number of bytes matches
745     ASSERT_EQ(p.unpack(v), 0);
746     // check that the payload was fully unpacked
747     ASSERT_TRUE(p.fullyUnpacked());
748     std::optional<std::tuple<uint8_t, uint32_t>> k{{0xbe, 0x04860002}};
749     // check that the bytes were correctly unpacked (in byte order)
750     ASSERT_EQ(v, k);
751 }
752 
TEST(UnpackAdvanced,OptionalInsufficientBytes)753 TEST(UnpackAdvanced, OptionalInsufficientBytes)
754 {
755     // a vector of bytes will be unpacked verbatim, low-order element first
756     ipmi::SecureBuffer i = {0x02, 0x00, 0x86, 0x04};
757     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
758     std::optional<std::tuple<uint8_t, uint32_t>> v;
759     // check that the number of bytes matches
760     ASSERT_EQ(p.unpack(v), 0);
761     // check that the payload was fully unpacked
762     ASSERT_FALSE(p.fullyUnpacked());
763     std::optional<std::tuple<uint8_t, uint32_t>> k;
764     // check that the bytes were correctly unpacked (in byte order)
765     ASSERT_EQ(v, k);
766 }
767 
TEST(UnpackAdvanced,Uints)768 TEST(UnpackAdvanced, Uints)
769 {
770     // all elements will be unpacked in order, with each multi-byte
771     // element being processed LSByte first
772     // v1[7:0] v2[7:0] v2[15:8] v3[7:0] v3[15:8] v3[23:16] v3[31:24]
773     // v4[7:0] v4[15:8] v4[23:16] v4[31:24]
774     // v4[39:25] v4[47:40] v4[55:48] v4[63:56]
775     ipmi::SecureBuffer i = {0x02, 0x04, 0x06, 0x11, 0x22, 0x33, 0x44, 0x55,
776                             0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc};
777     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
778     uint8_t v1;
779     uint16_t v2;
780     uint32_t v3;
781     uint64_t v4;
782     // check that the number of bytes matches
783     ASSERT_EQ(p.unpack(v1, v2, v3, v4), 0);
784     // check that the payload was fully unpacked
785     ASSERT_TRUE(p.fullyUnpacked());
786     uint8_t k1 = 0x02;
787     uint16_t k2 = 0x0604;
788     uint32_t k3 = 0x44332211;
789     uint64_t k4 = 0xccbbaa9988776655ull;
790     // check that the bytes were correctly unpacked (LSB first)
791     ASSERT_EQ(v1, k1);
792     ASSERT_EQ(v2, k2);
793     ASSERT_EQ(v3, k3);
794     ASSERT_EQ(v4, k4);
795 }
796 
TEST(UnpackAdvanced,TupleInts)797 TEST(UnpackAdvanced, TupleInts)
798 {
799     // all elements will be unpacked in order, with each multi-byte
800     // element being processed LSByte first
801     // v1[7:0] v2[7:0] v2[15:8] v3[7:0] v3[15:8] v3[23:16] v3[31:24]
802     // v4[7:0] v4[15:8] v4[23:16] v4[31:24]
803     // v4[39:25] v4[47:40] v4[55:48] v4[63:56]
804     ipmi::SecureBuffer i = {0x02, 0x04, 0x06, 0x11, 0x22, 0x33, 0x44, 0x55,
805                             0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc};
806     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
807     std::tuple<uint8_t, uint16_t, uint32_t, uint64_t> v;
808     // check that the number of bytes matches
809     ASSERT_EQ(p.unpack(v), 0);
810     // check that the payload was fully unpacked
811     ASSERT_TRUE(p.fullyUnpacked());
812     uint8_t k1 = 0x02;
813     uint16_t k2 = 0x0604;
814     uint32_t k3 = 0x44332211;
815     uint64_t k4 = 0xccbbaa9988776655ull;
816     auto k = std::make_tuple(k1, k2, k3, k4);
817     // check that the bytes were correctly unpacked (LSB first)
818     ASSERT_EQ(v, k);
819 }
820 
TEST(UnpackAdvanced,BoolsnBitfieldsnFixedIntsOhMy)821 TEST(UnpackAdvanced, BoolsnBitfieldsnFixedIntsOhMy)
822 {
823     // each element will be unpacked, filling the low-order bits first
824     // with multi-byte values getting unpacked LSByte first
825     // v1 will use k[0][1:0]
826     // v2 will use k[0][2]
827     // v3[4:0] will use k[0][7:3], v3[6:5] will use k[1][1:0]
828     // v4 will use k[1][2]
829     // v5 will use k[1][7:3]
830     ipmi::SecureBuffer i = {0x9e, 0xdb};
831     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
832     uint2_t v1;
833     bool v2;
834     std::bitset<7> v3;
835     bool v4;
836     uint5_t v5;
837     // check that the number of bytes matches
838     ASSERT_EQ(p.unpack(v1, v2, v3, v4, v5), 0);
839     // check that the payload was fully unpacked
840     ASSERT_TRUE(p.fullyUnpacked());
841     uint2_t k1 = 2;          // binary 0b10
842     bool k2 = true;          // binary 0b1
843     std::bitset<7> k3(0x73); // binary 0b1110011
844     bool k4 = false;         // binary 0b0
845     uint5_t k5 = 27;         // binary 0b11011
846     // check that the bytes were correctly unpacked (LSB first)
847     ASSERT_EQ(v1, k1);
848     ASSERT_EQ(v2, k2);
849     ASSERT_EQ(v3, k3);
850     ASSERT_EQ(v4, k4);
851     ASSERT_EQ(v5, k5);
852 }
853 
TEST(UnpackAdvanced,UnalignedBitUnpacking)854 TEST(UnpackAdvanced, UnalignedBitUnpacking)
855 {
856     // unaligned multi-byte values will be unpacked the same as
857     // other bits, effectively reading from a large value, low-order
858     // bits first, then consuming the stream LSByte first
859     // v1 will use k[0][1:0]
860     // v2[5:0] will use k[0][7:2], v2[7:6] will use k[1][1:0]
861     // v3 will use k[1][2]
862     // v4[4:0] will use k[1][7:3] v4[12:5] will use k[2][7:0]
863     // v4[15:13] will use k[3][2:0]
864     // v5 will use k[3][3]
865     // v6[3:0] will use k[3][7:0] v6[11:4] will use k[4][7:0]
866     // v6[19:12] will use k[5][7:0] v6[27:20] will use k[6][7:0]
867     // v6[31:28] will use k[7][3:0]
868     // v7 will use k[7][7:4]
869     ipmi::SecureBuffer i = {0x96, 0xd2, 0x2a, 0xcd, 0xd3, 0x3b, 0xbc, 0x9d};
870     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
871     uint2_t v1;
872     uint8_t v2;
873     bool v3;
874     uint16_t v4;
875     bool v5;
876     uint32_t v6;
877     uint4_t v7;
878     // check that the number of bytes matches
879     ASSERT_EQ(p.unpack(v1, v2, v3, v4, v5, v6, v7), 0);
880     // check that the payload was fully unpacked
881     ASSERT_TRUE(p.fullyUnpacked());
882     uint2_t k1 = 2;           // binary 0b10
883     uint8_t k2 = 0xa5;        // binary 0b10100101
884     bool k3 = false;          // binary 0b0
885     uint16_t k4 = 0xa55a;     // binary 0b1010010101011010
886     bool k5 = true;           // binary 0b1
887     uint32_t k6 = 0xdbc3bd3c; // binary 0b11011011110000111011110100111100
888     uint4_t k7 = 9;           // binary 0b1001
889     // check that the bytes were correctly unpacked (LSB first)
890     ASSERT_EQ(v1, k1);
891     ASSERT_EQ(v2, k2);
892     ASSERT_EQ(v3, k3);
893     ASSERT_EQ(v4, k4);
894     ASSERT_EQ(v5, k5);
895     ASSERT_EQ(v6, k6);
896     ASSERT_EQ(v7, k7);
897 }
898