1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
|
// Copyright 2019 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "libipp/ipp_encoding.h"
#include <vector>
#include <gtest/gtest.h>
namespace ipp {
namespace {
// Represents single test case.
struct TestCase {
// a value to read/write
int64_t value;
// 1-,2- and 4- bytes representations of the value in two's-complement binary
// encoding. Corresponding vector is empty <=> the value is out of range
// (cannot be saved on given number of bytes).
std::vector<uint8_t> as1byte;
std::vector<uint8_t> as2bytes;
std::vector<uint8_t> as4bytes;
// constructor
explicit TestCase(int64_t v) : value(v) {}
};
// All Test* templates below have the same parameters:
// BytesCount - 1, 2 or 4 - designated integer size in binary encoding
// Integer / SignedInteger / UnsignedInteger - type of parameter used in
// instantiation of tested template
// binary - one of the buffer from TestCase structure
// value - a value from TestCase structure
template <size_t BytesCount, typename Integer>
void TestReadSignedInt(const std::vector<uint8_t>& binary,
const int64_t value) {
const uint8_t* ptr = binary.data();
Integer out;
ParseSignedInteger<BytesCount, Integer>(&ptr, &out);
EXPECT_EQ(ptr, binary.data() + BytesCount);
EXPECT_EQ(out, value);
}
template <size_t BytesCount, typename Integer>
void TestReadUnsignedInt(const std::vector<uint8_t>& binary,
const int64_t value) {
const uint8_t* ptr = binary.data();
Integer out = 123;
const bool result = ParseUnsignedInteger<BytesCount, Integer>(&ptr, &out);
EXPECT_EQ(ptr, binary.data() + BytesCount);
if (value < 0) {
EXPECT_FALSE(result);
EXPECT_EQ(out, 123);
} else {
EXPECT_TRUE(result);
EXPECT_EQ(out, value);
}
}
template <size_t BytesCount, typename SignedInteger, typename UnsignedInteger>
void TestRead(const std::vector<uint8_t>& binary, const int64_t value) {
static_assert(std::is_integral<SignedInteger>::value, "integral expected");
static_assert(std::is_integral<UnsignedInteger>::value, "integral expected");
static_assert(std::is_signed<SignedInteger>::value, "signed expected");
static_assert(std::is_unsigned<UnsignedInteger>::value, "unsigned expected");
static_assert(sizeof(SignedInteger) == sizeof(UnsignedInteger),
"the same sizes expected");
if (!binary.empty()) {
ASSERT_EQ(BytesCount, binary.size());
TestReadSignedInt<BytesCount, SignedInteger>(binary, value);
TestReadUnsignedInt<BytesCount, SignedInteger>(binary, value);
TestReadUnsignedInt<BytesCount, UnsignedInteger>(binary, value);
}
}
template <size_t BytesCount, typename Integer>
void TestWriteInt(const std::vector<uint8_t>& binary, const Integer value) {
std::vector<uint8_t> buffer(BytesCount, 123);
uint8_t* ptr = buffer.data();
WriteInteger<BytesCount, Integer>(&ptr, value);
EXPECT_EQ(ptr, buffer.data() + BytesCount);
EXPECT_EQ(buffer, binary);
}
template <size_t BytesCount, typename Integer>
void TestWriteUnsigned(const std::vector<uint8_t>& binary,
const Integer value) {
std::vector<uint8_t> buffer(BytesCount, 123);
uint8_t* ptr = buffer.data();
WriteUnsigned<BytesCount, Integer>(&ptr, value);
EXPECT_EQ(ptr, buffer.data() + BytesCount);
EXPECT_EQ(buffer, binary);
}
template <size_t BytesCount, typename SignedInteger, typename UnsignedInteger>
void TestWrite(const std::vector<uint8_t>& binary, const int64_t value) {
static_assert(std::is_integral<SignedInteger>::value, "integral expected");
static_assert(std::is_integral<UnsignedInteger>::value, "integral expected");
static_assert(std::is_signed<SignedInteger>::value, "signed expected");
static_assert(std::is_unsigned<UnsignedInteger>::value, "unsigned expected");
static_assert(sizeof(SignedInteger) == sizeof(UnsignedInteger),
"the same sizes expected");
ASSERT_TRUE(BytesCount == binary.size() || binary.empty());
if ((value >= std::numeric_limits<SignedInteger>::min()) &&
(value <= std::numeric_limits<SignedInteger>::max())) {
TestWriteInt<BytesCount, SignedInteger>(binary, value);
}
if ((value >= 0) && (value <= std::numeric_limits<UnsignedInteger>::max())) {
TestWriteUnsigned<BytesCount, UnsignedInteger>(binary, value);
}
}
// Runs all possible tests for given TestCase.
void TestReadAndWrite(const TestCase& tc) {
// test read (only correct types are allowed)
TestRead<1, int8_t, uint8_t>(tc.as1byte, tc.value);
TestRead<1, int16_t, uint16_t>(tc.as1byte, tc.value);
TestRead<1, int32_t, uint32_t>(tc.as1byte, tc.value);
TestRead<2, int16_t, uint16_t>(tc.as2bytes, tc.value);
TestRead<2, int32_t, uint32_t>(tc.as2bytes, tc.value);
TestRead<4, int32_t, uint32_t>(tc.as4bytes, tc.value);
// test write (only matching types are allowed)
TestWrite<1, int8_t, uint8_t>(tc.as1byte, tc.value);
TestWrite<2, int16_t, uint16_t>(tc.as2bytes, tc.value);
TestWrite<4, int32_t, uint32_t>(tc.as4bytes, tc.value);
}
TEST(encoding, TwosComplementary0) {
TestCase tc(0);
tc.as1byte.resize(1, 0);
tc.as2bytes.resize(2, 0);
tc.as4bytes.resize(4, 0);
TestReadAndWrite(tc);
}
// min 1-byte int
TEST(encoding, TwosComplementaryNeg128) {
TestCase tc(-128);
tc.as1byte = {0x80};
tc.as2bytes = {0xff, 0x80};
tc.as4bytes = {0xff, 0xff, 0xff, 0x80};
TestReadAndWrite(tc);
}
// min 2-bytes int
TEST(encoding, TwosComplementaryNeg32768) {
TestCase tc(-32768);
tc.as2bytes = {0x80, 0x00};
tc.as4bytes = {0xff, 0xff, 0x80, 0x00};
TestReadAndWrite(tc);
}
// min 4-bytes int
TEST(encoding, TwosComplementaryNeg2147483648) {
TestCase tc(-2147483648);
tc.as4bytes = {0x80, 0x00, 0x00, 0x00};
TestReadAndWrite(tc);
}
// max 1-byte int
TEST(encoding, TwosComplementary127) {
TestCase tc(127);
tc.as1byte = {0x7f};
tc.as2bytes = {0x00, 0x7f};
tc.as4bytes = {0x00, 0x00, 0x00, 0x7f};
TestReadAndWrite(tc);
}
// max 2-bytes int
TEST(encoding, TwosComplementary32767) {
TestCase tc(32767);
tc.as2bytes = {0x7f, 0xff};
tc.as4bytes = {0x00, 0x00, 0x7f, 0xff};
TestReadAndWrite(tc);
}
// max 4-bytes int
TEST(encoding, TwosComplementary2147483647) {
TestCase tc(2147483647);
tc.as4bytes = {0x7f, 0xff, 0xff, 0xff};
TestReadAndWrite(tc);
}
} // end of namespace
} // end of namespace ipp
|