blob: bcfa73e6eae245c5aa56f7d9abef5c7a28931cec [file] [log] [blame]
#include <endian.h>
#include <stdplus/raw.hpp>
#include <array>
#include <span>
#include <stdexcept>
#include <string_view>
#include <vector>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
namespace stdplus
{
namespace raw
{
namespace
{
TEST(Equal, Equal)
{
int a = 4;
unsigned b = 4;
EXPECT_TRUE(equal(a, b));
b = 5;
EXPECT_FALSE(equal(a, b));
}
TEST(CopyFrom, Empty)
{
const std::string_view cs;
EXPECT_THROW(copyFrom<int>(cs), exception::Incomplete);
std::string_view s;
EXPECT_THROW(copyFrom<int>(s), exception::Incomplete);
EXPECT_THROW(copyFromStrict<char>(s), exception::Incomplete);
}
TEST(CopyFrom, Basic)
{
int a = 4;
const std::string_view s(reinterpret_cast<char*>(&a), sizeof(a));
EXPECT_EQ(a, copyFrom<int>(s));
EXPECT_EQ(a, copyFromStrict<int>(s));
}
TEST(CopyFrom, Partial)
{
const std::vector<char> s = {'a', 'b', 'c'};
EXPECT_EQ('a', copyFrom<char>(s));
EXPECT_THROW(copyFromStrict<char>(s), exception::Incomplete);
const char s2[] = "def";
EXPECT_EQ('d', copyFrom<char>(s2));
}
struct Int
{
uint8_t data[sizeof(int)];
inline bool operator==(const Int& other) const
{
return memcmp(data, other.data, sizeof(data)) == 0;
}
};
TEST(RefFrom, Empty)
{
const std::string_view cs;
EXPECT_THROW(refFrom<Int>(cs), exception::Incomplete);
std::string_view s;
EXPECT_THROW(refFrom<Int>(s), exception::Incomplete);
EXPECT_THROW(refFromStrict<Int>(s), exception::Incomplete);
}
TEST(RefFrom, Basic)
{
Int a = {4, 0, 0, 4};
const std::string_view s(reinterpret_cast<char*>(&a), sizeof(a));
EXPECT_EQ(a, refFrom<Int>(s));
EXPECT_EQ(a, refFromStrict<Int>(s));
}
TEST(RefFrom, Partial)
{
const std::vector<char> s = {'a', 'b', 'c'};
EXPECT_EQ('a', refFrom<char>(s));
EXPECT_THROW(refFromStrict<char>(s), exception::Incomplete);
const char s2[] = "def";
EXPECT_EQ('d', refFrom<char>(s2));
}
TEST(Extract, TooSmall)
{
std::string str = "aaaa";
str.resize(1);
std::string_view s(str);
EXPECT_THROW(extract<int>(s), exception::Incomplete);
EXPECT_EQ("a", s);
}
TEST(Extract, Basic)
{
int a = 4;
std::string_view s(reinterpret_cast<char*>(&a), sizeof(a));
EXPECT_EQ(a, extract<int>(s));
EXPECT_TRUE(s.empty());
}
TEST(Extract, Partial)
{
std::string_view s("abc");
EXPECT_EQ('a', extract<char>(s));
EXPECT_EQ("bc", s);
}
TEST(ExtractRef, TooSmall)
{
// Trick the compiler with a bigger buffer so it doesn't complain
std::array<char, sizeof(Int)> buf{};
buf[0] = 'a';
std::string_view s(buf.data(), 1);
EXPECT_THROW(extractRef<Int>(s), exception::Incomplete);
EXPECT_EQ("a", s);
}
TEST(ExtractRef, Basic)
{
Int a = {4, 0, 0, 4};
std::string_view s(reinterpret_cast<char*>(&a), sizeof(a));
EXPECT_EQ(a, extractRef<Int>(s));
EXPECT_TRUE(s.empty());
}
TEST(ExtractRef, Partial)
{
std::string_view s("abc");
EXPECT_EQ('a', extractRef<char>(s));
EXPECT_EQ("bc", s);
}
TEST(AsView, Byte)
{
int32_t a = 4;
auto s = asView<uint8_t>(a);
EXPECT_EQ(a, copyFrom<int>(s));
}
TEST(AsView, Int)
{
int32_t a = 4;
auto s = asView<char16_t>(a);
EXPECT_EQ(a, copyFrom<int>(s));
}
using testing::ElementsAre;
using testing::ElementsAreArray;
TEST(AsView, Array)
{
std::vector<uint32_t> arr = {htole32(1), htole32(2)};
auto s = asView<char16_t>(arr);
EXPECT_THAT(s, ElementsAre(htole16(1), htole16(0), htole16(2), htole16(0)));
}
TEST(AsView, StringView)
{
std::string_view sv = "ab";
auto s = asView<uint8_t>(sv);
EXPECT_THAT(s, ElementsAreArray(sv));
}
TEST(SpanExtract, TooSmall)
{
const std::vector<char> v = {'c'};
std::span<const char> s = v;
EXPECT_THROW(extract<int>(s), exception::Incomplete);
EXPECT_THAT(s, ElementsAreArray(v));
}
TEST(SpanExtract, Basic)
{
const std::vector<int> v = {4};
std::span<const int> s = v;
EXPECT_EQ(v[0], extract<int>(s));
EXPECT_TRUE(s.empty());
}
TEST(SpanExtract, Larger)
{
const std::vector<int> v{3, 4, 5};
std::span<const int> s = v;
EXPECT_EQ(v[0], extract<int>(s));
EXPECT_THAT(s, ElementsAre(v[1], v[2]));
}
TEST(SpanExtractRef, TooSmall)
{
const std::vector<char> v = {'c'};
std::span<const char> s = v;
EXPECT_THROW(extractRef<Int>(s), exception::Incomplete);
EXPECT_THAT(s, ElementsAreArray(v));
}
TEST(SpanExtractRef, Basic)
{
const std::vector<Int> v = {{4, 0, 0, 4}};
std::span<const Int> s = v;
EXPECT_EQ(v[0], extractRef<Int>(s));
EXPECT_TRUE(s.empty());
}
TEST(SpanExtractRef, Larger)
{
const std::vector<Int> v{{3}, {4}, {5}};
std::span<const Int> s = v;
EXPECT_EQ(v[0], extractRef<Int>(s));
EXPECT_THAT(s, ElementsAre(v[1], v[2]));
}
TEST(AsSpan, ConstInt)
{
const uint64_t data = htole64(0xffff0000);
auto s = asSpan<uint32_t>(data);
EXPECT_THAT(s, ElementsAre(htole32(0xffff0000), htole32(0x00000000)));
}
TEST(AsSpan, ConstArray)
{
const std::vector<uint32_t> arr = {htole32(1), htole32(2)};
auto s = asSpan<uint16_t>(arr);
EXPECT_THAT(s, ElementsAre(htole16(1), htole16(0), htole16(2), htole16(0)));
}
TEST(AsSpan, Int)
{
struct
{
uint64_t a;
uint64_t* data()
{
return &a;
}
} data = {htole64(0xffff0000)};
auto s = asSpan<uint16_t>(data);
EXPECT_THAT(s, ElementsAre(htole16(0x0000), htole16(0xffff),
htole16(0x0000), htole16(0x0000)));
s[2] = 0xfefe;
EXPECT_THAT(s, ElementsAre(htole16(0x0000), htole16(0xffff),
htole16(0xfefe), htole16(0x0000)));
}
TEST(AsSpan, Array)
{
std::vector<uint32_t> arr = {htole32(1), htole32(2)};
auto s = asSpan<uint16_t>(arr);
EXPECT_THAT(s, ElementsAre(htole16(1), htole16(0), htole16(2), htole16(0)));
}
TEST(AsSpan, Span)
{
std::array<char, 2> arr = {'a', 'b'};
auto sp1 = std::span<const char>(arr);
auto s1 = asSpan<uint8_t>(sp1);
EXPECT_THAT(s1, ElementsAreArray(arr));
auto sp2 = std::span<char>(arr);
auto s2 = asSpan<uint8_t>(sp2);
EXPECT_THAT(s2, ElementsAreArray(arr));
}
} // namespace
} // namespace raw
} // namespace stdplus