summaryrefslogtreecommitdiffstats
path: root/test/message/payload.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/message/payload.cpp')
-rw-r--r--test/message/payload.cpp308
1 files changed, 308 insertions, 0 deletions
diff --git a/test/message/payload.cpp b/test/message/payload.cpp
new file mode 100644
index 0000000..9d20ff0
--- /dev/null
+++ b/test/message/payload.cpp
@@ -0,0 +1,308 @@
+/**
+ * Copyright © 2018 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <ipmid/api.hpp>
+#include <ipmid/message.hpp>
+
+#include <gtest/gtest.h>
+
+TEST(Payload, InputSize)
+{
+ std::vector<uint8_t> i = {0xbf, 0x04, 0x86, 0x00, 0x02};
+ size_t input_size = i.size();
+ ipmi::message::Payload p(std::forward<std::vector<uint8_t>>(i));
+ ASSERT_EQ(input_size, p.size());
+}
+
+TEST(Payload, OutputSize)
+{
+ ipmi::message::Payload p;
+ ASSERT_EQ(0, p.size());
+ std::vector<uint8_t> i = {0xbf, 0x04, 0x86, 0x00, 0x02};
+ p.pack(i);
+ ASSERT_EQ(i.size(), p.size());
+ p.pack(i);
+ p.pack(i);
+ ASSERT_EQ(3 * i.size(), p.size());
+}
+
+TEST(Payload, Resize)
+{
+ std::vector<uint8_t> i = {0xbf, 0x04, 0x86, 0x00, 0x02};
+ ipmi::message::Payload p;
+ p.pack(i);
+ p.resize(16);
+ ASSERT_EQ(p.size(), 16);
+}
+
+TEST(Payload, Data)
+{
+ std::vector<uint8_t> i = {0xbf, 0x04, 0x86, 0x00, 0x02};
+ ipmi::message::Payload p;
+ p.pack(i);
+ ASSERT_NE(nullptr, p.data());
+}
+
+TEST(PayloadResponse, Append)
+{
+ std::string s("0123456789abcdef");
+ ipmi::message::Payload p;
+ p.append(s.data(), s.data() + s.size());
+ ASSERT_EQ(s.size(), p.size());
+}
+
+TEST(PayloadResponse, AppendDrain)
+{
+ std::string s("0123456789abcdef");
+ ipmi::message::Payload p;
+ bool b = true;
+ // first pack a lone bit
+ p.pack(b);
+ p.append(s.data(), s.data() + s.size());
+ // append will 'drain' first, padding the lone bit into a full byte
+ ASSERT_EQ(s.size() + 1, p.size());
+}
+
+TEST(PayloadResponse, AppendBits)
+{
+ ipmi::message::Payload p;
+ p.appendBits(3, 0b101);
+ ASSERT_EQ(p.bitStream, 0b101);
+ p.appendBits(4, 0b1100);
+ ASSERT_EQ(p.bitStream, 0b1100101);
+ p.appendBits(1, 0b1);
+ ASSERT_EQ(p.bitStream, 0);
+ ASSERT_EQ(p.bitCount, 0);
+ // appended 8 bits, should be one byte
+ ASSERT_EQ(p.size(), 1);
+ std::vector<uint8_t> k1 = {0b11100101};
+ ASSERT_EQ(p.raw, k1);
+ p.appendBits(7, 0b1110111);
+ // appended 7 more bits, should still be one byte
+ ASSERT_EQ(p.size(), 1);
+ p.drain();
+ // drain forces padding; should be two bytes now
+ ASSERT_EQ(p.size(), 2);
+ std::vector<uint8_t> k2 = {0b11100101, 0b01110111};
+ ASSERT_EQ(p.raw, k2);
+}
+
+TEST(PayloadResponse, Drain16Bits)
+{
+ ipmi::message::Payload p;
+ p.bitStream = 0b1011010011001111;
+ p.bitCount = 16;
+ p.drain();
+ ASSERT_EQ(p.size(), 2);
+ ASSERT_EQ(p.bitCount, 0);
+ ASSERT_EQ(p.bitStream, 0);
+ std::vector<uint8_t> k1 = {0b11001111, 0b10110100};
+ ASSERT_EQ(p.raw, k1);
+}
+
+TEST(PayloadResponse, Drain15Bits)
+{
+ ipmi::message::Payload p;
+ p.bitStream = 0b101101001100111;
+ p.bitCount = 15;
+ p.drain();
+ ASSERT_EQ(p.size(), 2);
+ ASSERT_EQ(p.bitCount, 0);
+ ASSERT_EQ(p.bitStream, 0);
+ std::vector<uint8_t> k1 = {0b1100111, 0b1011010};
+ ASSERT_EQ(p.raw, k1);
+}
+
+TEST(PayloadResponse, Drain15BitsWholeBytesOnly)
+{
+ ipmi::message::Payload p;
+ p.bitStream = 0b101101001100111;
+ p.bitCount = 15;
+ p.drain(true);
+ // only the first whole byte should have been 'drained' into p.raw
+ ASSERT_EQ(p.size(), 1);
+ ASSERT_EQ(p.bitCount, 7);
+ ASSERT_EQ(p.bitStream, 0b1011010);
+ std::vector<uint8_t> k1 = {0b1100111};
+ ASSERT_EQ(p.raw, k1);
+}
+
+TEST(PayloadRequest, Pop)
+{
+ std::vector<uint8_t> i = {0xbf, 0x04, 0x86, 0x00, 0x02};
+ ipmi::message::Payload p(std::forward<std::vector<uint8_t>>(i));
+ const auto& [vb, ve] = p.pop<uint8_t>(4);
+ std::vector<uint8_t> v(vb, ve);
+ std::vector<uint8_t> k = {0xbf, 0x04, 0x86, 0x00};
+ ASSERT_EQ(v, k);
+}
+
+TEST(PayloadRequest, FillBits)
+{
+ std::vector<uint8_t> i = {0xbf, 0x04, 0x86, 0x00, 0x02};
+ ipmi::message::Payload p(std::forward<std::vector<uint8_t>>(i));
+ p.fillBits(5);
+ ASSERT_FALSE(p.unpackError);
+ ASSERT_EQ(p.bitStream, 0xbf);
+ ASSERT_EQ(p.bitCount, 8);
+ // should still have 5 bits available, no change
+ p.fillBits(5);
+ ASSERT_FALSE(p.unpackError);
+ ASSERT_EQ(p.bitStream, 0xbf);
+ ASSERT_EQ(p.bitCount, 8);
+ // discard 5 bits (low order)
+ p.popBits(5);
+ // should add another byte into the stream (high order)
+ p.fillBits(5);
+ ASSERT_FALSE(p.unpackError);
+ ASSERT_EQ(p.bitStream, 0x25);
+ ASSERT_EQ(p.bitCount, 11);
+}
+
+TEST(PayloadRequest, FillBitsTooManyBits)
+{
+ std::vector<uint8_t> i = {1, 2, 3, 4, 5, 6, 7, 8, 9};
+ ipmi::message::Payload p(std::forward<std::vector<uint8_t>>(i));
+ p.fillBits(72);
+ ASSERT_TRUE(p.unpackError);
+}
+
+TEST(PayloadRequest, FillBitsNotEnoughBytes)
+{
+ std::vector<uint8_t> i = {1, 2, 3, 4};
+ ipmi::message::Payload p(std::forward<std::vector<uint8_t>>(i));
+ p.fillBits(48);
+ ASSERT_TRUE(p.unpackError);
+}
+
+TEST(PayloadRequest, PopBits)
+{
+ std::vector<uint8_t> i = {0xbf, 0x04, 0x86, 0x00, 0x02};
+ ipmi::message::Payload p(std::forward<std::vector<uint8_t>>(i));
+ p.fillBits(4);
+ uint8_t v = p.popBits(4);
+ ASSERT_FALSE(p.unpackError);
+ ASSERT_EQ(p.bitStream, 0x0b);
+ ASSERT_EQ(p.bitCount, 4);
+ ASSERT_EQ(v, 0x0f);
+}
+
+TEST(PayloadRequest, PopBitsNoFillBits)
+{
+ std::vector<uint8_t> i = {0xbf, 0x04, 0x86, 0x00, 0x02};
+ ipmi::message::Payload p(std::forward<std::vector<uint8_t>>(i));
+ p.popBits(4);
+ ASSERT_TRUE(p.unpackError);
+}
+
+TEST(PayloadRequest, DiscardBits)
+{
+ std::vector<uint8_t> i = {0xbf, 0x04, 0x86, 0x00, 0x02};
+ ipmi::message::Payload p(std::forward<std::vector<uint8_t>>(i));
+ p.fillBits(5);
+ ASSERT_FALSE(p.unpackError);
+ ASSERT_EQ(p.bitStream, 0xbf);
+ ASSERT_EQ(p.bitCount, 8);
+ p.discardBits();
+ ASSERT_FALSE(p.unpackError);
+ ASSERT_EQ(p.bitStream, 0);
+ ASSERT_EQ(p.bitCount, 0);
+}
+
+TEST(PayloadRequest, FullyUnpacked)
+{
+ std::vector<uint8_t> i = {0xbf, 0x04, 0x86, 0x00, 0x02};
+ ipmi::message::Payload p(std::forward<std::vector<uint8_t>>(i));
+ uint32_t v1;
+ p.unpack(v1);
+ // still one remaining byte
+ ASSERT_FALSE(p.fullyUnpacked());
+ p.fillBits(3);
+ p.popBits(3);
+ // still five remaining bits
+ ASSERT_FALSE(p.fullyUnpacked());
+ p.fillBits(5);
+ p.popBits(5);
+ // fully unpacked, should be no errors
+ ASSERT_TRUE(p.fullyUnpacked());
+ p.fillBits(4);
+ // fullyUnpacked fails because an attempt to unpack too many bytes
+ ASSERT_FALSE(p.fullyUnpacked());
+}
+
+TEST(PayloadRequest, ResetInternal)
+{
+ std::vector<uint8_t> i = {0xbf, 0x04, 0x86, 0x00, 0x02};
+ ipmi::message::Payload p(std::forward<std::vector<uint8_t>>(i));
+ p.fillBits(4);
+ p.unpackError = true;
+ p.reset();
+ ASSERT_EQ(p.rawIndex, 0);
+ ASSERT_EQ(p.bitStream, 0);
+ ASSERT_EQ(p.bitCount, 0);
+ ASSERT_FALSE(p.unpackError);
+}
+
+TEST(PayloadRequest, ResetUsage)
+{
+ // Payload.reset is used to rewind the unpacking to the initial
+ // state. This is needed so that OEM commands can unpack the group
+ // number or the IANA to determine which handler needs to be called
+ std::vector<uint8_t> i = {0x04, 0x86};
+ ipmi::message::Payload p(std::forward<std::vector<uint8_t>>(i));
+ uint8_t v1;
+ // check that the number of bytes matches
+ ASSERT_EQ(p.unpack(v1), 0);
+ // check that the payload was not fully unpacked
+ ASSERT_FALSE(p.fullyUnpacked());
+ uint8_t k1 = 0x04;
+ // check that the bytes were correctly unpacked (LSB first)
+ ASSERT_EQ(v1, k1);
+ // do a reset on the payload
+ p.reset();
+ // unpack a uint16
+ uint16_t v2;
+ // check that the number of bytes matches
+ ASSERT_EQ(p.unpack(v2), 0);
+ // check that the payload was fully unpacked
+ ASSERT_TRUE(p.fullyUnpacked());
+ uint16_t k2 = 0x8604;
+ // check that the bytes were correctly unpacked (LSB first)
+ ASSERT_EQ(v2, k2);
+}
+
+TEST(PayloadRequest, PartialPayload)
+{
+ std::vector<uint8_t> i = {0xbf, 0x04, 0x86, 0x00, 0x02};
+ ipmi::message::Payload p(std::forward<std::vector<uint8_t>>(i));
+ uint8_t v1;
+ ipmi::message::Payload localPayload;
+ // check that the number of bytes matches
+ ASSERT_EQ(p.unpack(v1, localPayload), 0);
+ // check that the payload was partially unpacked and not in error
+ ASSERT_FALSE(p.fullyUnpacked());
+ ASSERT_FALSE(p.unpackError);
+ // check that the 'extracted' payload is not fully unpacked
+ ASSERT_FALSE(localPayload.fullyUnpacked());
+ uint8_t k1 = 0xbf;
+ // check that the bytes were correctly unpacked (LSB first)
+ ASSERT_EQ(v1, k1);
+ uint32_t v2;
+ // unpack using the 'extracted' payload
+ ASSERT_EQ(localPayload.unpack(v2), 0);
+ ASSERT_TRUE(localPayload.fullyUnpacked());
+ uint32_t k2 = 0x02008604;
+ ASSERT_EQ(v2, k2);
+}
OpenPOWER on IntegriCloud