//===-------- SimplePackedSerializationTest.cpp - Test SPS scheme ---------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "llvm/ExecutionEngine/Orc/Shared/SimplePackedSerialization.h" #include "gtest/gtest.h" using namespace llvm; using namespace llvm::orc::shared; TEST(SimplePackedSerializationTest, SPSOutputBuffer) { constexpr unsigned NumBytes = 8; char Buffer[NumBytes]; char Zero = 0; SPSOutputBuffer OB(Buffer, NumBytes); // Expect that we can write NumBytes of content. for (unsigned I = 0; I != NumBytes; ++I) { char C = I; EXPECT_TRUE(OB.write(&C, 1)); } // Expect an error when we attempt to write an extra byte. EXPECT_FALSE(OB.write(&Zero, 1)); // Check that the buffer contains the expected content. for (unsigned I = 0; I != NumBytes; ++I) EXPECT_EQ(Buffer[I], (char)I); } TEST(SimplePackedSerializationTest, SPSInputBuffer) { char Buffer[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; SPSInputBuffer IB(Buffer, sizeof(Buffer)); char C; for (unsigned I = 0; I != sizeof(Buffer); ++I) { EXPECT_TRUE(IB.read(&C, 1)); EXPECT_EQ(C, (char)I); } EXPECT_FALSE(IB.read(&C, 1)); } template static void spsSerializationRoundTrip(const T &Value) { using BST = SPSSerializationTraits; size_t Size = BST::size(Value); auto Buffer = std::make_unique(Size); SPSOutputBuffer OB(Buffer.get(), Size); EXPECT_TRUE(BST::serialize(OB, Value)); SPSInputBuffer IB(Buffer.get(), Size); T DSValue; EXPECT_TRUE(BST::deserialize(IB, DSValue)); EXPECT_EQ(Value, DSValue) << "Incorrect value after serialization/deserialization round-trip"; } template static void testFixedIntegralTypeSerialization() { spsSerializationRoundTrip(0); spsSerializationRoundTrip(static_cast(1)); if (std::is_signed_v) { spsSerializationRoundTrip(static_cast(-1)); spsSerializationRoundTrip(std::numeric_limits::min()); } spsSerializationRoundTrip(std::numeric_limits::max()); } TEST(SimplePackedSerializationTest, BoolSerialization) { spsSerializationRoundTrip(true); spsSerializationRoundTrip(false); } TEST(SimplePackedSerializationTest, CharSerialization) { spsSerializationRoundTrip((char)0x00); spsSerializationRoundTrip((char)0xAA); spsSerializationRoundTrip((char)0xFF); } TEST(SimplePackedSerializationTest, Int8Serialization) { testFixedIntegralTypeSerialization(); } TEST(SimplePackedSerializationTest, UInt8Serialization) { testFixedIntegralTypeSerialization(); } TEST(SimplePackedSerializationTest, Int16Serialization) { testFixedIntegralTypeSerialization(); } TEST(SimplePackedSerializationTest, UInt16Serialization) { testFixedIntegralTypeSerialization(); } TEST(SimplePackedSerializationTest, Int32Serialization) { testFixedIntegralTypeSerialization(); } TEST(SimplePackedSerializationTest, UInt32Serialization) { testFixedIntegralTypeSerialization(); } TEST(SimplePackedSerializationTest, Int64Serialization) { testFixedIntegralTypeSerialization(); } TEST(SimplePackedSerializationTest, UInt64Serialization) { testFixedIntegralTypeSerialization(); } TEST(SimplePackedSerializationTest, SequenceSerialization) { std::vector V({1, 2, -47, 139}); spsSerializationRoundTrip>(V); } TEST(SimplePackedSerializationTest, StringViewCharSequenceSerialization) { const char *HW = "Hello, world!"; spsSerializationRoundTrip(StringRef(HW)); } TEST(SimplePackedSerializationTest, StdTupleSerialization) { std::tuple P(42, "foo", true); spsSerializationRoundTrip>(P); } TEST(SimplePackedSerializationTest, StdPairSerialization) { std::pair P(42, "foo"); spsSerializationRoundTrip>(P); } TEST(SimplePackedSerializationTest, StdOptionalNoValueSerialization) { std::optional NoValue; spsSerializationRoundTrip>(NoValue); } TEST(SimplePackedSerializationTest, StdOptionalValueSerialization) { std::optional Value(42); spsSerializationRoundTrip>(Value); } TEST(SimplePackedSerializationTest, ArgListSerialization) { using BAL = SPSArgList; bool Arg1 = true; int32_t Arg2 = 42; std::string Arg3 = "foo"; size_t Size = BAL::size(Arg1, Arg2, Arg3); auto Buffer = std::make_unique(Size); SPSOutputBuffer OB(Buffer.get(), Size); EXPECT_TRUE(BAL::serialize(OB, Arg1, Arg2, Arg3)); SPSInputBuffer IB(Buffer.get(), Size); bool ArgOut1; int32_t ArgOut2; std::string ArgOut3; EXPECT_TRUE(BAL::deserialize(IB, ArgOut1, ArgOut2, ArgOut3)); EXPECT_EQ(Arg1, ArgOut1); EXPECT_EQ(Arg2, ArgOut2); EXPECT_EQ(Arg3, ArgOut3); } TEST(SimplePackedSerialization, StringMap) { StringMap M({{"A", 1}, {"B", 2}}); spsSerializationRoundTrip>>(M); } TEST(SimplePackedSerializationTest, ArrayRef) { constexpr unsigned BufferSize = 6 + 8; // "hello\0" + sizeof(uint64_t) ArrayRef HelloOut = "hello"; char Buffer[BufferSize]; memset(Buffer, 0, BufferSize); SPSOutputBuffer OB(Buffer, BufferSize); EXPECT_TRUE(SPSArgList>::serialize(OB, HelloOut)); ArrayRef HelloIn; SPSInputBuffer IB(Buffer, BufferSize); EXPECT_TRUE(SPSArgList>::deserialize(IB, HelloIn)); // Output should be copied to buffer. EXPECT_NE(HelloOut.data(), Buffer); // Input should reference buffer. EXPECT_LT(HelloIn.data() - Buffer, BufferSize); } TEST(SimplePackedSerializationTest, ArrayRefEmpty) { // Make sure that empty ArrayRefs serialize and deserialize as expected. // Empty ArrayRefs should not succeed even when the data field is null, and // should deserialize to a default-constructed ArrayRef, not a pointer into // the stream. constexpr unsigned BufferSize = sizeof(uint64_t); char Buffer[BufferSize]; memset(Buffer, 0, BufferSize); ArrayRef AOut; SPSOutputBuffer OB(Buffer, BufferSize); EXPECT_TRUE(SPSArgList>::serialize(OB, AOut)); ArrayRef AIn; SPSInputBuffer IB(Buffer, BufferSize); EXPECT_TRUE(SPSArgList>::deserialize(IB, AIn)); EXPECT_EQ(AIn.data(), nullptr); EXPECT_EQ(AIn.size(), 0U); } TEST(SimplePackedSerializationTest, StringRefEmpty) { // Make sure that empty StringRefs serialize and deserialize as expected. // Empty StringRefs should not succeed even when the data field is null, and // should deserialize to a default-constructed StringRef, not a pointer into // the stream. constexpr unsigned BufferSize = sizeof(uint64_t); char Buffer[BufferSize]; memset(Buffer, 0, BufferSize); StringRef SROut; SPSOutputBuffer OB(Buffer, BufferSize); EXPECT_TRUE(SPSArgList>::serialize(OB, SROut)); StringRef SRIn; SPSInputBuffer IB(Buffer, BufferSize); EXPECT_TRUE(SPSArgList>::deserialize(IB, SRIn)); EXPECT_EQ(SRIn.data(), nullptr); EXPECT_EQ(SRIn.size(), 0U); }