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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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     std::bitset<33> k(0);
504     // check that v is zero
505     ASSERT_EQ(v, 0);
506 }
507 
508 TEST(Arrays, Array4xUint8)
509 {
510     // an array of bytes will be read verbatim, low-order element first
511     ipmi::SecureBuffer i = {0x02, 0x00, 0x86, 0x04};
512     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
513     std::array<uint8_t, 4> v;
514     // check that the number of bytes matches
515     ASSERT_EQ(p.unpack(v), 0);
516     // check that the payload was fully unpacked
517     ASSERT_TRUE(p.fullyUnpacked());
518     std::array<uint8_t, 4> k = {{0x02, 0x00, 0x86, 0x04}};
519     // check that the bytes were correctly unpacked (in byte order)
520     ASSERT_EQ(v, k);
521 }
522 
523 TEST(Arrays, Array4xUint8TooManyBytes)
524 {
525     // last byte should not get unpacked
526     // an array of bytes will be read verbatim, low-order element first
527     ipmi::SecureBuffer i = {0x02, 0x00, 0x86, 0x04, 0x22};
528     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
529     std::array<uint8_t, 4> v;
530     // check that the number of bytes matches
531     ASSERT_EQ(p.unpack(v), 0);
532     // check that the payload was not fully unpacked
533     ASSERT_FALSE(p.fullyUnpacked());
534     std::array<uint8_t, 4> k = {{0x02, 0x00, 0x86, 0x04}};
535     // check that the bytes were correctly unpacked (in byte order)
536     ASSERT_EQ(v, k);
537 }
538 
539 TEST(Arrays, Array4xUint8InsufficientBytes)
540 {
541     // last byte should not get unpacked
542     // an array of bytes will be read verbatim, low-order element first
543     ipmi::SecureBuffer i = {0x02, 0x00, 0x86};
544     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
545     std::array<uint8_t, 4> v;
546     // check that the number of bytes matches
547     ASSERT_NE(p.unpack(v), 0);
548     // check that the payload was not fully unpacked
549     ASSERT_FALSE(p.fullyUnpacked());
550     // arrays of uint8_t will be unpacked all at once
551     // so nothing will get unpacked
552     std::array<uint8_t, 4> k = {{0, 0, 0, 0}};
553     // check that the bytes were correctly unpacked (in byte order)
554     ASSERT_EQ(v, k);
555 }
556 
557 TEST(Arrays, Array4xUint32)
558 {
559     // an array of multi-byte values will be unpacked in order low-order
560     // element first, each multi-byte element in LSByte order
561     // v[0][7:0] v[0][15:9] v[0][23:16] v[0][31:24]
562     // v[1][7:0] v[1][15:9] v[1][23:16] v[1][31:24]
563     // v[2][7:0] v[2][15:9] v[2][23:16] v[2][31:24]
564     // v[3][7:0] v[3][15:9] v[3][23:16] v[3][31:24]
565     ipmi::SecureBuffer i = {0x44, 0x33, 0x22, 0x11, 0x88, 0x66, 0x44, 0x22,
566                             0x99, 0x77, 0x55, 0x33, 0x78, 0x56, 0x34, 0x12};
567     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
568     std::array<uint32_t, 4> v;
569     // check that the number of bytes matches
570     ASSERT_EQ(p.unpack(v), 0);
571     // check that the payload was fully unpacked
572     ASSERT_TRUE(p.fullyUnpacked());
573     std::array<uint32_t, 4> k = {
574         {0x11223344, 0x22446688, 0x33557799, 0x12345678}};
575     // check that the bytes were correctly unpacked (in byte order)
576     ASSERT_EQ(v, k);
577 }
578 
579 TEST(Arrays, Array4xUint32TooManyBytes)
580 {
581     // last byte should not get unpacked
582     // an array of multi-byte values will be unpacked in order low-order
583     // element first, each multi-byte element in LSByte order
584     // v[0][7:0] v[0][15:9] v[0][23:16] v[0][31:24]
585     // v[1][7:0] v[1][15:9] v[1][23:16] v[1][31:24]
586     // v[2][7:0] v[2][15:9] v[2][23:16] v[2][31:24]
587     // v[3][7:0] v[3][15:9] v[3][23:16] v[3][31:24]
588     ipmi::SecureBuffer i = {0x44, 0x33, 0x22, 0x11, 0x88, 0x66,
589                             0x44, 0x22, 0x99, 0x77, 0x55, 0x33,
590                             0x78, 0x56, 0x34, 0x12, 0xaa};
591     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
592     std::array<uint32_t, 4> v;
593     // check that the number of bytes matches
594     ASSERT_EQ(p.unpack(v), 0);
595     // check that the payload was not fully unpacked
596     ASSERT_FALSE(p.fullyUnpacked());
597     std::array<uint32_t, 4> k = {
598         {0x11223344, 0x22446688, 0x33557799, 0x12345678}};
599     // check that the bytes were correctly unpacked (in byte order)
600     ASSERT_EQ(v, k);
601 }
602 
603 TEST(Arrays, Array4xUint32InsufficientBytes)
604 {
605     // last value should not get unpacked
606     // an array of multi-byte values will be unpacked in order low-order
607     // element first, each multi-byte element in LSByte order
608     // v[0][7:0] v[0][15:9] v[0][23:16] v[0][31:24]
609     // v[1][7:0] v[1][15:9] v[1][23:16] v[1][31:24]
610     // v[2][7:0] v[2][15:9] v[2][23:16] v[2][31:24]
611     // v[3][7:0] v[3][15:9] v[3][23:16] v[3][31:24]
612     ipmi::SecureBuffer i = {0x44, 0x33, 0x22, 0x11, 0x88, 0x66, 0x44, 0x22,
613                             0x99, 0x77, 0x55, 0x33, 0x78, 0x56, 0x34};
614     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
615     std::array<uint32_t, 4> v;
616     // check that the number of bytes matches
617     ASSERT_NE(p.unpack(v), 0);
618     // check that the payload was not fully unpacked
619     ASSERT_FALSE(p.fullyUnpacked());
620     // arrays of uint32_t will be unpacked in a way that looks atomic
621     std::array<uint32_t, 4> k = {{0, 0, 0, 0}};
622     // check that the bytes were correctly unpacked (in byte order)
623     ASSERT_EQ(v, k);
624 }
625 
626 TEST(Vectors, VectorUint32)
627 {
628     // a vector of multi-byte values will be unpacked in order low-order
629     // element first, each multi-byte element in LSByte order
630     // v[0][7:0] v[0][15:9] v[0][23:16] v[0][31:24]
631     // v[1][7:0] v[1][15:9] v[1][23:16] v[1][31:24]
632     // v[2][7:0] v[2][15:9] v[2][23:16] v[2][31:24]
633     // v[3][7:0] v[3][15:9] v[3][23:16] v[3][31:24]
634     ipmi::SecureBuffer i = {0x44, 0x33, 0x22, 0x11, 0x88, 0x66, 0x44, 0x22,
635                             0x99, 0x77, 0x55, 0x33, 0x78, 0x56, 0x34, 0x12};
636     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
637     std::vector<uint32_t> v;
638     // check that the number of bytes matches
639     ASSERT_EQ(p.unpack(v), 0);
640     // check that the payload was fully unpacked
641     ASSERT_TRUE(p.fullyUnpacked());
642     std::vector<uint32_t> k = {0x11223344, 0x22446688, 0x33557799, 0x12345678};
643     // check that the bytes were correctly unpacked (in byte order)
644     ASSERT_EQ(v, k);
645 }
646 
647 // combination of TooManyBytes and InsufficientBytes because
648 // vectors will attempt to unpack full <T>s until the end of the input
649 TEST(Vectors, VectorUint32NonIntegralBytes)
650 {
651     // last value should not get unpacked
652     // a vector of multi-byte values will be unpacked in order low-order
653     // element first, each multi-byte element in LSByte order,
654     // and will attempt to consume all bytes remaining
655     // v[0][7:0] v[0][15:9] v[0][23:16] v[0][31:24]
656     // v[1][7:0] v[1][15:9] v[1][23:16] v[1][31:24]
657     // v[2][7:0] v[2][15:9] v[2][23:16] v[2][31:24]
658     // v[3][7:0] v[3][15:9] v[3][23:16] v[3][31:24]
659     ipmi::SecureBuffer i = {0x44, 0x33, 0x22, 0x11, 0x88, 0x66, 0x44, 0x22,
660                             0x99, 0x77, 0x55, 0x33, 0x78, 0x56, 0x34};
661     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
662     std::vector<uint32_t> v;
663     // check that the vector unpacks successfully
664     ASSERT_EQ(p.unpack(v), 0);
665     // check that the payload was not fully unpacked
666     ASSERT_FALSE(p.fullyUnpacked());
667     // arrays of uint32_t will be unpacked one at a time, so the
668     // last entry should not get unpacked properly
669     std::vector<uint32_t> k = {0x11223344, 0x22446688, 0x33557799};
670     // check that the bytes were correctly unpacked (in byte order)
671     ASSERT_EQ(v, k);
672 }
673 
674 TEST(Vectors, VectorUint8)
675 {
676     // a vector of bytes will be unpacked verbatim, low-order element first
677     ipmi::SecureBuffer i = {0x02, 0x00, 0x86, 0x04};
678     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
679     std::vector<uint8_t> v;
680     // check that the number of bytes matches
681     ASSERT_EQ(p.unpack(v), 0);
682     // check that the payload was fully unpacked
683     ASSERT_TRUE(p.fullyUnpacked());
684     std::vector<uint8_t> k = {0x02, 0x00, 0x86, 0x04};
685     // check that the bytes were correctly unpacked (in byte order)
686     ASSERT_EQ(v, k);
687 }
688 
689 TEST(Vectors, VectorEmptyOk)
690 {
691     // an empty input vector to show that unpacking elements is okay
692     ipmi::SecureBuffer i{};
693     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
694     std::vector<uint32_t> v;
695     // check that the number of bytes matches
696     ASSERT_EQ(p.unpack(v), 0);
697     // check that the payload was fully unpacked
698     ASSERT_TRUE(p.fullyUnpacked());
699     std::vector<uint32_t> k{};
700     // check that the unpacked vector is empty as expected
701     ASSERT_EQ(v, k);
702 }
703 
704 TEST(Vectors, VectorOfTuplesOk)
705 {
706     // a vector of bytes will be unpacked verbatim, low-order element first
707     ipmi::SecureBuffer i = {0x02, 0x00, 0x86, 0x04};
708     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
709     std::vector<std::tuple<uint8_t, uint8_t>> v;
710     // check that the number of bytes matches
711     ASSERT_EQ(p.unpack(v), 0);
712     // check that the payload was fully unpacked
713     ASSERT_TRUE(p.fullyUnpacked());
714     std::vector<std::tuple<uint8_t, uint8_t>> k = {{0x02, 0x00}, {0x86, 0x04}};
715     // check that the bytes were correctly unpacked (in byte order)
716     ASSERT_EQ(v, k);
717 }
718 
719 TEST(Vectors, VectorOfTuplesInsufficientBytes)
720 {
721     // a vector of bytes will be unpacked verbatim, low-order element first
722     ipmi::SecureBuffer i = {0x02, 0x00, 0x86, 0x04, 0xb4};
723     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
724     std::vector<std::tuple<uint8_t, uint8_t>> v;
725     // check that the number of bytes matches
726     ASSERT_EQ(p.unpack(v), 0);
727     // check that the payload was not fully unpacked
728     ASSERT_FALSE(p.fullyUnpacked());
729     std::vector<std::tuple<uint8_t, uint8_t>> k = {{0x02, 0x00}, {0x86, 0x04}};
730     // check that the bytes were correctly unpacked (in byte order)
731     ASSERT_EQ(v, k);
732 }
733 
734 // Cannot test TooManyBytes or InsufficientBytes for vector<uint8_t>
735 // because it will always unpack whatever bytes are remaining
736 // TEST(Vectors, VectorUint8TooManyBytes) {}
737 // TEST(Vectors, VectorUint8InsufficientBytes) {}
738 
739 TEST(UnpackAdvanced, OptionalOk)
740 {
741     // a vector of bytes will be unpacked verbatim, low-order element first
742     ipmi::SecureBuffer i = {0xbe, 0x02, 0x00, 0x86, 0x04};
743     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
744     std::optional<std::tuple<uint8_t, uint32_t>> v;
745     // check that the number of bytes matches
746     ASSERT_EQ(p.unpack(v), 0);
747     // check that the payload was fully unpacked
748     ASSERT_TRUE(p.fullyUnpacked());
749     std::optional<std::tuple<uint8_t, uint32_t>> k{{0xbe, 0x04860002}};
750     // check that the bytes were correctly unpacked (in byte order)
751     ASSERT_EQ(v, k);
752 }
753 
754 TEST(UnpackAdvanced, OptionalInsufficientBytes)
755 {
756     // a vector of bytes will be unpacked verbatim, low-order element first
757     ipmi::SecureBuffer i = {0x02, 0x00, 0x86, 0x04};
758     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
759     std::optional<std::tuple<uint8_t, uint32_t>> v;
760     // check that the number of bytes matches
761     ASSERT_EQ(p.unpack(v), 0);
762     // check that the payload was fully unpacked
763     ASSERT_FALSE(p.fullyUnpacked());
764     std::optional<std::tuple<uint8_t, uint32_t>> k;
765     // check that the bytes were correctly unpacked (in byte order)
766     ASSERT_EQ(v, k);
767 }
768 
769 TEST(UnpackAdvanced, Uints)
770 {
771     // all elements will be unpacked in order, with each multi-byte
772     // element being processed LSByte first
773     // v1[7:0] v2[7:0] v2[15:8] v3[7:0] v3[15:8] v3[23:16] v3[31:24]
774     // v4[7:0] v4[15:8] v4[23:16] v4[31:24]
775     // v4[39:25] v4[47:40] v4[55:48] v4[63:56]
776     ipmi::SecureBuffer i = {0x02, 0x04, 0x06, 0x11, 0x22, 0x33, 0x44, 0x55,
777                             0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc};
778     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
779     uint8_t v1;
780     uint16_t v2;
781     uint32_t v3;
782     uint64_t v4;
783     // check that the number of bytes matches
784     ASSERT_EQ(p.unpack(v1, v2, v3, v4), 0);
785     // check that the payload was fully unpacked
786     ASSERT_TRUE(p.fullyUnpacked());
787     uint8_t k1 = 0x02;
788     uint16_t k2 = 0x0604;
789     uint32_t k3 = 0x44332211;
790     uint64_t k4 = 0xccbbaa9988776655ull;
791     // check that the bytes were correctly unpacked (LSB first)
792     ASSERT_EQ(v1, k1);
793     ASSERT_EQ(v2, k2);
794     ASSERT_EQ(v3, k3);
795     ASSERT_EQ(v4, k4);
796 }
797 
798 TEST(UnpackAdvanced, TupleInts)
799 {
800     // all elements will be unpacked in order, with each multi-byte
801     // element being processed LSByte first
802     // v1[7:0] v2[7:0] v2[15:8] v3[7:0] v3[15:8] v3[23:16] v3[31:24]
803     // v4[7:0] v4[15:8] v4[23:16] v4[31:24]
804     // v4[39:25] v4[47:40] v4[55:48] v4[63:56]
805     ipmi::SecureBuffer i = {0x02, 0x04, 0x06, 0x11, 0x22, 0x33, 0x44, 0x55,
806                             0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc};
807     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
808     std::tuple<uint8_t, uint16_t, uint32_t, uint64_t> v;
809     // check that the number of bytes matches
810     ASSERT_EQ(p.unpack(v), 0);
811     // check that the payload was fully unpacked
812     ASSERT_TRUE(p.fullyUnpacked());
813     uint8_t k1 = 0x02;
814     uint16_t k2 = 0x0604;
815     uint32_t k3 = 0x44332211;
816     uint64_t k4 = 0xccbbaa9988776655ull;
817     auto k = std::make_tuple(k1, k2, k3, k4);
818     // check that the bytes were correctly unpacked (LSB first)
819     ASSERT_EQ(v, k);
820 }
821 
822 TEST(UnpackAdvanced, BoolsnBitfieldsnFixedIntsOhMy)
823 {
824     // each element will be unpacked, filling the low-order bits first
825     // with multi-byte values getting unpacked LSByte first
826     // v1 will use k[0][1:0]
827     // v2 will use k[0][2]
828     // v3[4:0] will use k[0][7:3], v3[6:5] will use k[1][1:0]
829     // v4 will use k[1][2]
830     // v5 will use k[1][7:3]
831     ipmi::SecureBuffer i = {0x9e, 0xdb};
832     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
833     uint2_t v1;
834     bool v2;
835     std::bitset<7> v3;
836     bool v4;
837     uint5_t v5;
838     // check that the number of bytes matches
839     ASSERT_EQ(p.unpack(v1, v2, v3, v4, v5), 0);
840     // check that the payload was fully unpacked
841     ASSERT_TRUE(p.fullyUnpacked());
842     uint2_t k1 = 2;          // binary 0b10
843     bool k2 = true;          // binary 0b1
844     std::bitset<7> k3(0x73); // binary 0b1110011
845     bool k4 = false;         // binary 0b0
846     uint5_t k5 = 27;         // binary 0b11011
847     // check that the bytes were correctly unpacked (LSB first)
848     ASSERT_EQ(v1, k1);
849     ASSERT_EQ(v2, k2);
850     ASSERT_EQ(v3, k3);
851     ASSERT_EQ(v4, k4);
852     ASSERT_EQ(v5, k5);
853 }
854 
855 TEST(UnpackAdvanced, UnalignedBitUnpacking)
856 {
857     // unaligned multi-byte values will be unpacked the same as
858     // other bits, effectively reading from a large value, low-order
859     // bits first, then consuming the stream LSByte first
860     // v1 will use k[0][1:0]
861     // v2[5:0] will use k[0][7:2], v2[7:6] will use k[1][1:0]
862     // v3 will use k[1][2]
863     // v4[4:0] will use k[1][7:3] v4[12:5] will use k[2][7:0]
864     // v4[15:13] will use k[3][2:0]
865     // v5 will use k[3][3]
866     // v6[3:0] will use k[3][7:0] v6[11:4] will use k[4][7:0]
867     // v6[19:12] will use k[5][7:0] v6[27:20] will use k[6][7:0]
868     // v6[31:28] will use k[7][3:0]
869     // v7 will use k[7][7:4]
870     ipmi::SecureBuffer i = {0x96, 0xd2, 0x2a, 0xcd, 0xd3, 0x3b, 0xbc, 0x9d};
871     ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
872     uint2_t v1;
873     uint8_t v2;
874     bool v3;
875     uint16_t v4;
876     bool v5;
877     uint32_t v6;
878     uint4_t v7;
879     // check that the number of bytes matches
880     ASSERT_EQ(p.unpack(v1, v2, v3, v4, v5, v6, v7), 0);
881     // check that the payload was fully unpacked
882     ASSERT_TRUE(p.fullyUnpacked());
883     uint2_t k1 = 2;           // binary 0b10
884     uint8_t k2 = 0xa5;        // binary 0b10100101
885     bool k3 = false;          // binary 0b0
886     uint16_t k4 = 0xa55a;     // binary 0b1010010101011010
887     bool k5 = true;           // binary 0b1
888     uint32_t k6 = 0xdbc3bd3c; // binary 0b11011011110000111011110100111100
889     uint4_t k7 = 9;           // binary 0b1001
890     // check that the bytes were correctly unpacked (LSB first)
891     ASSERT_EQ(v1, k1);
892     ASSERT_EQ(v2, k2);
893     ASSERT_EQ(v3, k3);
894     ASSERT_EQ(v4, k4);
895     ASSERT_EQ(v5, k5);
896     ASSERT_EQ(v6, k6);
897     ASSERT_EQ(v7, k7);
898 }
899