blob: 59316948c7cfffbd5927e9d59a1908d6502e4e8e [file] [log] [blame]
Vernon Maueryebe8e902018-12-12 09:39:22 -08001/**
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 */
William A. Kennington III51694c22019-04-24 01:44:44 -070016#define SD_JOURNAL_SUPPRESS_LOCATION
17
18#include <systemd/sd-journal.h>
19
Vernon Maueryebe8e902018-12-12 09:39:22 -080020#include <ipmid/api.hpp>
21#include <ipmid/message.hpp>
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -050022
William A. Kennington IIIf2fd17a2019-04-24 01:53:52 -070023#include <stdexcept>
Vernon Maueryebe8e902018-12-12 09:39:22 -080024
25#include <gtest/gtest.h>
26
27TEST(Payload, InputSize)
28{
Vernon Mauery997952a2021-07-30 14:06:14 -070029 ipmi::SecureBuffer i = {0xbf, 0x04, 0x86, 0x00, 0x02};
Vernon Maueryebe8e902018-12-12 09:39:22 -080030 size_t input_size = i.size();
Vernon Mauery997952a2021-07-30 14:06:14 -070031 ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
Vernon Maueryebe8e902018-12-12 09:39:22 -080032 ASSERT_EQ(input_size, p.size());
33}
34
35TEST(Payload, OutputSize)
36{
37 ipmi::message::Payload p;
38 ASSERT_EQ(0, p.size());
Vernon Mauery997952a2021-07-30 14:06:14 -070039 ipmi::SecureBuffer i = {0xbf, 0x04, 0x86, 0x00, 0x02};
Vernon Maueryebe8e902018-12-12 09:39:22 -080040 p.pack(i);
41 ASSERT_EQ(i.size(), p.size());
42 p.pack(i);
43 p.pack(i);
44 ASSERT_EQ(3 * i.size(), p.size());
45}
46
47TEST(Payload, Resize)
48{
Vernon Mauery997952a2021-07-30 14:06:14 -070049 ipmi::SecureBuffer i = {0xbf, 0x04, 0x86, 0x00, 0x02};
Vernon Maueryebe8e902018-12-12 09:39:22 -080050 ipmi::message::Payload p;
51 p.pack(i);
52 p.resize(16);
53 ASSERT_EQ(p.size(), 16);
54}
55
56TEST(Payload, Data)
57{
Vernon Mauery997952a2021-07-30 14:06:14 -070058 ipmi::SecureBuffer i = {0xbf, 0x04, 0x86, 0x00, 0x02};
Vernon Maueryebe8e902018-12-12 09:39:22 -080059 ipmi::message::Payload p;
60 p.pack(i);
61 ASSERT_NE(nullptr, p.data());
62}
63
64TEST(PayloadResponse, Append)
65{
66 std::string s("0123456789abcdef");
67 ipmi::message::Payload p;
68 p.append(s.data(), s.data() + s.size());
69 ASSERT_EQ(s.size(), p.size());
70}
71
72TEST(PayloadResponse, AppendDrain)
73{
74 std::string s("0123456789abcdef");
75 ipmi::message::Payload p;
76 bool b = true;
77 // first pack a lone bit
78 p.pack(b);
79 p.append(s.data(), s.data() + s.size());
80 // append will 'drain' first, padding the lone bit into a full byte
81 ASSERT_EQ(s.size() + 1, p.size());
82}
83
84TEST(PayloadResponse, AppendBits)
85{
86 ipmi::message::Payload p;
87 p.appendBits(3, 0b101);
88 ASSERT_EQ(p.bitStream, 0b101);
89 p.appendBits(4, 0b1100);
90 ASSERT_EQ(p.bitStream, 0b1100101);
91 p.appendBits(1, 0b1);
92 ASSERT_EQ(p.bitStream, 0);
93 ASSERT_EQ(p.bitCount, 0);
94 // appended 8 bits, should be one byte
95 ASSERT_EQ(p.size(), 1);
Vernon Mauery997952a2021-07-30 14:06:14 -070096 ipmi::SecureBuffer k1 = {0b11100101};
Vernon Maueryebe8e902018-12-12 09:39:22 -080097 ASSERT_EQ(p.raw, k1);
98 p.appendBits(7, 0b1110111);
99 // appended 7 more bits, should still be one byte
100 ASSERT_EQ(p.size(), 1);
101 p.drain();
102 // drain forces padding; should be two bytes now
103 ASSERT_EQ(p.size(), 2);
Vernon Mauery997952a2021-07-30 14:06:14 -0700104 ipmi::SecureBuffer k2 = {0b11100101, 0b01110111};
Vernon Maueryebe8e902018-12-12 09:39:22 -0800105 ASSERT_EQ(p.raw, k2);
106}
107
108TEST(PayloadResponse, Drain16Bits)
109{
110 ipmi::message::Payload p;
111 p.bitStream = 0b1011010011001111;
112 p.bitCount = 16;
113 p.drain();
114 ASSERT_EQ(p.size(), 2);
115 ASSERT_EQ(p.bitCount, 0);
116 ASSERT_EQ(p.bitStream, 0);
Vernon Mauery997952a2021-07-30 14:06:14 -0700117 ipmi::SecureBuffer k1 = {0b11001111, 0b10110100};
Vernon Maueryebe8e902018-12-12 09:39:22 -0800118 ASSERT_EQ(p.raw, k1);
119}
120
121TEST(PayloadResponse, Drain15Bits)
122{
123 ipmi::message::Payload p;
124 p.bitStream = 0b101101001100111;
125 p.bitCount = 15;
126 p.drain();
127 ASSERT_EQ(p.size(), 2);
128 ASSERT_EQ(p.bitCount, 0);
129 ASSERT_EQ(p.bitStream, 0);
Vernon Mauery997952a2021-07-30 14:06:14 -0700130 ipmi::SecureBuffer k1 = {0b1100111, 0b1011010};
Vernon Maueryebe8e902018-12-12 09:39:22 -0800131 ASSERT_EQ(p.raw, k1);
132}
133
134TEST(PayloadResponse, Drain15BitsWholeBytesOnly)
135{
136 ipmi::message::Payload p;
137 p.bitStream = 0b101101001100111;
138 p.bitCount = 15;
139 p.drain(true);
140 // only the first whole byte should have been 'drained' into p.raw
141 ASSERT_EQ(p.size(), 1);
142 ASSERT_EQ(p.bitCount, 7);
143 ASSERT_EQ(p.bitStream, 0b1011010);
Vernon Mauery997952a2021-07-30 14:06:14 -0700144 ipmi::SecureBuffer k1 = {0b1100111};
Vernon Maueryebe8e902018-12-12 09:39:22 -0800145 ASSERT_EQ(p.raw, k1);
146}
147
148TEST(PayloadRequest, Pop)
149{
Vernon Mauery997952a2021-07-30 14:06:14 -0700150 ipmi::SecureBuffer i = {0xbf, 0x04, 0x86, 0x00, 0x02};
151 ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
Vernon Maueryebe8e902018-12-12 09:39:22 -0800152 const auto& [vb, ve] = p.pop<uint8_t>(4);
153 std::vector<uint8_t> v(vb, ve);
154 std::vector<uint8_t> k = {0xbf, 0x04, 0x86, 0x00};
155 ASSERT_EQ(v, k);
156}
157
158TEST(PayloadRequest, FillBits)
159{
Vernon Mauery997952a2021-07-30 14:06:14 -0700160 ipmi::SecureBuffer i = {0xbf, 0x04, 0x86, 0x00, 0x02};
161 ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
Vernon Maueryebe8e902018-12-12 09:39:22 -0800162 p.fillBits(5);
163 ASSERT_FALSE(p.unpackError);
164 ASSERT_EQ(p.bitStream, 0xbf);
165 ASSERT_EQ(p.bitCount, 8);
166 // should still have 5 bits available, no change
167 p.fillBits(5);
168 ASSERT_FALSE(p.unpackError);
169 ASSERT_EQ(p.bitStream, 0xbf);
170 ASSERT_EQ(p.bitCount, 8);
171 // discard 5 bits (low order)
172 p.popBits(5);
173 // should add another byte into the stream (high order)
174 p.fillBits(5);
175 ASSERT_FALSE(p.unpackError);
176 ASSERT_EQ(p.bitStream, 0x25);
177 ASSERT_EQ(p.bitCount, 11);
178}
179
180TEST(PayloadRequest, FillBitsTooManyBits)
181{
Vernon Mauery997952a2021-07-30 14:06:14 -0700182 ipmi::SecureBuffer i = {1, 2, 3, 4, 5, 6, 7, 8, 9};
183 ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
Vernon Maueryebe8e902018-12-12 09:39:22 -0800184 p.fillBits(72);
185 ASSERT_TRUE(p.unpackError);
186}
187
188TEST(PayloadRequest, FillBitsNotEnoughBytes)
189{
Vernon Mauery997952a2021-07-30 14:06:14 -0700190 ipmi::SecureBuffer i = {1, 2, 3, 4};
191 ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
Vernon Maueryebe8e902018-12-12 09:39:22 -0800192 p.fillBits(48);
193 ASSERT_TRUE(p.unpackError);
194}
195
196TEST(PayloadRequest, PopBits)
197{
Vernon Mauery997952a2021-07-30 14:06:14 -0700198 ipmi::SecureBuffer i = {0xbf, 0x04, 0x86, 0x00, 0x02};
199 ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
Vernon Maueryebe8e902018-12-12 09:39:22 -0800200 p.fillBits(4);
201 uint8_t v = p.popBits(4);
202 ASSERT_FALSE(p.unpackError);
203 ASSERT_EQ(p.bitStream, 0x0b);
204 ASSERT_EQ(p.bitCount, 4);
205 ASSERT_EQ(v, 0x0f);
206}
207
208TEST(PayloadRequest, PopBitsNoFillBits)
209{
Vernon Mauery997952a2021-07-30 14:06:14 -0700210 ipmi::SecureBuffer i = {0xbf, 0x04, 0x86, 0x00, 0x02};
211 ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
Vernon Maueryebe8e902018-12-12 09:39:22 -0800212 p.popBits(4);
213 ASSERT_TRUE(p.unpackError);
214}
215
216TEST(PayloadRequest, DiscardBits)
217{
Vernon Mauery997952a2021-07-30 14:06:14 -0700218 ipmi::SecureBuffer i = {0xbf, 0x04, 0x86, 0x00, 0x02};
219 ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
Vernon Maueryebe8e902018-12-12 09:39:22 -0800220 p.fillBits(5);
221 ASSERT_FALSE(p.unpackError);
222 ASSERT_EQ(p.bitStream, 0xbf);
223 ASSERT_EQ(p.bitCount, 8);
224 p.discardBits();
225 ASSERT_FALSE(p.unpackError);
226 ASSERT_EQ(p.bitStream, 0);
227 ASSERT_EQ(p.bitCount, 0);
228}
229
230TEST(PayloadRequest, FullyUnpacked)
231{
Vernon Mauery997952a2021-07-30 14:06:14 -0700232 ipmi::SecureBuffer i = {0xbf, 0x04, 0x86, 0x00, 0x02};
233 ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
Vernon Maueryebe8e902018-12-12 09:39:22 -0800234 uint32_t v1;
235 p.unpack(v1);
236 // still one remaining byte
237 ASSERT_FALSE(p.fullyUnpacked());
238 p.fillBits(3);
239 p.popBits(3);
240 // still five remaining bits
241 ASSERT_FALSE(p.fullyUnpacked());
242 p.fillBits(5);
243 p.popBits(5);
244 // fully unpacked, should be no errors
245 ASSERT_TRUE(p.fullyUnpacked());
246 p.fillBits(4);
247 // fullyUnpacked fails because an attempt to unpack too many bytes
248 ASSERT_FALSE(p.fullyUnpacked());
249}
250
251TEST(PayloadRequest, ResetInternal)
252{
Vernon Mauery997952a2021-07-30 14:06:14 -0700253 ipmi::SecureBuffer i = {0xbf, 0x04, 0x86, 0x00, 0x02};
254 ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
Vernon Maueryebe8e902018-12-12 09:39:22 -0800255 p.fillBits(4);
256 p.unpackError = true;
257 p.reset();
258 ASSERT_EQ(p.rawIndex, 0);
259 ASSERT_EQ(p.bitStream, 0);
260 ASSERT_EQ(p.bitCount, 0);
261 ASSERT_FALSE(p.unpackError);
262}
263
264TEST(PayloadRequest, ResetUsage)
265{
266 // Payload.reset is used to rewind the unpacking to the initial
267 // state. This is needed so that OEM commands can unpack the group
268 // number or the IANA to determine which handler needs to be called
Vernon Mauery997952a2021-07-30 14:06:14 -0700269 ipmi::SecureBuffer i = {0x04, 0x86};
270 ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
Vernon Maueryebe8e902018-12-12 09:39:22 -0800271 uint8_t v1;
272 // check that the number of bytes matches
273 ASSERT_EQ(p.unpack(v1), 0);
274 // check that the payload was not fully unpacked
275 ASSERT_FALSE(p.fullyUnpacked());
276 uint8_t k1 = 0x04;
277 // check that the bytes were correctly unpacked (LSB first)
278 ASSERT_EQ(v1, k1);
279 // do a reset on the payload
280 p.reset();
281 // unpack a uint16
282 uint16_t v2;
283 // check that the number of bytes matches
284 ASSERT_EQ(p.unpack(v2), 0);
285 // check that the payload was fully unpacked
286 ASSERT_TRUE(p.fullyUnpacked());
287 uint16_t k2 = 0x8604;
288 // check that the bytes were correctly unpacked (LSB first)
289 ASSERT_EQ(v2, k2);
290}
291
292TEST(PayloadRequest, PartialPayload)
293{
Vernon Mauery997952a2021-07-30 14:06:14 -0700294 ipmi::SecureBuffer i = {0xbf, 0x04, 0x86, 0x00, 0x02};
295 ipmi::message::Payload p(std::forward<ipmi::SecureBuffer>(i));
Vernon Maueryebe8e902018-12-12 09:39:22 -0800296 uint8_t v1;
297 ipmi::message::Payload localPayload;
298 // check that the number of bytes matches
299 ASSERT_EQ(p.unpack(v1, localPayload), 0);
300 // check that the payload was partially unpacked and not in error
301 ASSERT_FALSE(p.fullyUnpacked());
302 ASSERT_FALSE(p.unpackError);
303 // check that the 'extracted' payload is not fully unpacked
304 ASSERT_FALSE(localPayload.fullyUnpacked());
305 uint8_t k1 = 0xbf;
306 // check that the bytes were correctly unpacked (LSB first)
307 ASSERT_EQ(v1, k1);
308 uint32_t v2;
309 // unpack using the 'extracted' payload
310 ASSERT_EQ(localPayload.unpack(v2), 0);
311 ASSERT_TRUE(localPayload.fullyUnpacked());
312 uint32_t k2 = 0x02008604;
313 ASSERT_EQ(v2, k2);
314}
William A. Kennington III51694c22019-04-24 01:44:44 -0700315
316std::vector<std::string> logs;
317
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500318extern "C"
William A. Kennington III51694c22019-04-24 01:44:44 -0700319{
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500320 int sd_journal_send(const char* format, ...)
321 {
322 logs.push_back(format);
323 return 0;
324 }
William A. Kennington III51694c22019-04-24 01:44:44 -0700325
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500326 int sd_journal_send_with_location(const char* /*file*/,
327 const char* /*line*/,
328 const char* /*func*/, const char* format,
329 ...)
330 {
331 logs.push_back(format);
332 return 0;
333 }
William A. Kennington III51694c22019-04-24 01:44:44 -0700334}
335
336class PayloadLogging : public testing::Test
337{
338 public:
339 void SetUp()
340 {
341 logs.clear();
342 }
343};
344
345TEST_F(PayloadLogging, TrailingOk)
346{
347 {
348 ipmi::message::Payload p({1, 2});
349 }
350 EXPECT_EQ(logs.size(), 0);
351}
352
353TEST_F(PayloadLogging, EnforcingUnchecked)
354{
355 {
356 ipmi::message::Payload p({1, 2});
357 p.trailingOk = false;
358 }
359 EXPECT_EQ(logs.size(), 1);
360}
361
362TEST_F(PayloadLogging, EnforcingUncheckedUnpacked)
363{
364 {
365 ipmi::message::Payload p({1, 2});
366 p.trailingOk = false;
367 uint8_t out;
368 p.unpack(out, out);
369 }
370 EXPECT_EQ(logs.size(), 1);
371}
372
373TEST_F(PayloadLogging, EnforcingUncheckedError)
374{
375 {
376 ipmi::message::Payload p({1, 2});
377 p.trailingOk = false;
378 uint32_t out;
379 p.unpack(out);
380 }
381 EXPECT_EQ(logs.size(), 0);
382}
383
384TEST_F(PayloadLogging, EnforcingChecked)
385{
386 {
387 ipmi::message::Payload p({1, 2});
388 p.trailingOk = false;
389 EXPECT_FALSE(p.fullyUnpacked());
390 }
391 EXPECT_EQ(logs.size(), 0);
392}
393
394TEST_F(PayloadLogging, EnforcingCheckedUnpacked)
395{
396 {
397 ipmi::message::Payload p({1, 2});
398 p.trailingOk = false;
399 uint8_t out;
400 p.unpack(out, out);
401 EXPECT_TRUE(p.fullyUnpacked());
402 }
403 EXPECT_EQ(logs.size(), 0);
404}
405
406TEST_F(PayloadLogging, EnforcingUnpackPayload)
407{
408 {
409 ipmi::message::Payload p;
410 {
411 ipmi::message::Payload q({1, 2});
412 q.trailingOk = false;
413 q.unpack(p);
414 }
415 EXPECT_EQ(logs.size(), 0);
416 }
417 EXPECT_EQ(logs.size(), 1);
418}
419
420TEST_F(PayloadLogging, EnforcingMove)
421{
422 {
423 ipmi::message::Payload p;
424 {
425 ipmi::message::Payload q({1, 2});
426 q.trailingOk = false;
427 p = std::move(q);
428 }
429 EXPECT_EQ(logs.size(), 0);
430 }
431 EXPECT_EQ(logs.size(), 1);
432}
William A. Kennington IIIf2fd17a2019-04-24 01:53:52 -0700433
434TEST_F(PayloadLogging, EnforcingException)
435{
436 try
437 {
438 ipmi::message::Payload p({1, 2});
439 p.trailingOk = false;
440 throw std::runtime_error("test");
441 }
442 catch (...)
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500443 {}
William A. Kennington IIIf2fd17a2019-04-24 01:53:52 -0700444 EXPECT_EQ(logs.size(), 0);
445}