//===- SimplePackedSerializationTest.cpp ----------------------------------===// // // 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 // //===----------------------------------------------------------------------===// // // Tests for SimplePackedSerialization infrastructure. // //===----------------------------------------------------------------------===// #include "orc-rt/SimplePackedSerialization.h" #include "SimplePackedSerializationTestUtils.h" #include "gtest/gtest.h" using namespace orc_rt; 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 testFixedIntegralTypeSerialization() { blobSerializationRoundTrip(0); blobSerializationRoundTrip(static_cast(1)); if (std::is_signed::value) { blobSerializationRoundTrip(static_cast(-1)); blobSerializationRoundTrip(std::numeric_limits::min()); } blobSerializationRoundTrip(std::numeric_limits::max()); } TEST(SimplePackedSerializationTest, BoolSerialization) { blobSerializationRoundTrip(true); blobSerializationRoundTrip(false); } TEST(SimplePackedSerializationTest, CharSerialization) { blobSerializationRoundTrip((char)0x00); blobSerializationRoundTrip((char)0xAA); blobSerializationRoundTrip((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, SizeTSerialization) { size_t V = 42; blobSerializationRoundTrip(V); } TEST(SimplePackedSerializationTest, SequenceSerialization) { std::vector V({1, 2, -47, 139}); blobSerializationRoundTrip, std::vector>(V); } TEST(SimplePackedSerializationTest, ExecutorAddr) { int X = 42; auto A = ExecutorAddr::fromPtr(&X); blobSerializationRoundTrip(A); } TEST(SimplePackedSerializationTest, StringViewCharSequenceSerialization) { const char *HW = "Hello, world!"; blobSerializationRoundTrip(std::string_view(HW)); } TEST(SimplePackedSerializationTest, SpanSerialization) { const char Data[] = {3, 2, 1, 0, 1, 2, 3}; // Span should handle nulls. span OutS(Data, sizeof(Data)); size_t Size = SPSArgList>::size(OutS); auto Buffer = std::make_unique(Size); SPSOutputBuffer OB(Buffer.get(), Size); EXPECT_TRUE(SPSArgList>::serialize(OB, OutS)); SPSInputBuffer IB(Buffer.get(), Size); span InS; EXPECT_TRUE(SPSArgList>::deserialize(IB, InS)); // Check that the serialized and deserialized values match. EXPECT_EQ(InS.size(), OutS.size()); EXPECT_EQ(memcmp(OutS.data(), InS.data(), InS.size()), 0); // Check that the span points directly to the input buffer. EXPECT_EQ(InS.data(), Buffer.get() + sizeof(uint64_t)); } TEST(SimplePackedSerializationTest, StdTupleSerialization) { std::tuple P(42, "foo", true); blobSerializationRoundTrip>(P); } TEST(SimplePackedSerializationTest, StdPairSerialization) { std::pair P(42, "foo"); blobSerializationRoundTrip, std::pair>(P); } TEST(SimplePackedSerializationTest, StdOptionalNoValueSerialization) { std::optional NoValue; blobSerializationRoundTrip>(NoValue); } TEST(SimplePackedSerializationTest, StdOptionalValueSerialization) { std::optional Value(42); blobSerializationRoundTrip>(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(SimplePackedSerializationTest, SerializeErrorSuccess) { auto B = spsSerialize>( SPSSerializableError(Error::success())); if (!B) { ADD_FAILURE() << "Unexpected failure to serialize error-success value"; return; } SPSSerializableError SE; if (!spsDeserialize>(*B, SE)) { ADD_FAILURE() << "Unexpected failure to deserialize error-success value"; return; } auto E = SE.toError(); EXPECT_FALSE(!!E); // Expect non-error, i.e. Error::success(). } TEST(SimplePackedSerializationTest, SerializeErrorFailure) { auto B = spsSerialize>( SPSSerializableError(make_error("test error message"))); if (!B) { ADD_FAILURE() << "Unexpected failure to serialize error-failure value"; return; } SPSSerializableError SE; if (!spsDeserialize>(*B, SE)) { ADD_FAILURE() << "Unexpected failure to deserialize error-failure value"; return; } EXPECT_EQ(toString(SE.toError()), std::string("test error message")); } TEST(SimplePackedSerializationTest, SerializeExpectedSuccessViaExpected) { auto B = spsSerialize>>( toSPSSerializableExpected(Expected(42U))); if (!B) { ADD_FAILURE() << "Unexpected failure to serialize expected-success value"; return; } SPSSerializableExpected SE; if (!spsDeserialize>>(*B, SE)) { ADD_FAILURE() << "Unexpected failure to deserialize expected-success value"; return; } auto E = SE.toExpected(); if (E) EXPECT_EQ(*E, 42U); else ADD_FAILURE() << "Unexpected failure value"; } TEST(SimplePackedSerializationTest, SerializeExpectedSuccessViaValue) { auto B = spsSerialize>>( toSPSSerializableExpected(uint32_t(42U))); if (!B) { ADD_FAILURE() << "Unexpected failure to serialize expected-success value"; return; } SPSSerializableExpected SE; if (!spsDeserialize>>(*B, SE)) { ADD_FAILURE() << "Unexpected failure to deserialize expected-success value"; return; } auto E = SE.toExpected(); if (E) EXPECT_EQ(*E, 42U); else ADD_FAILURE() << "Unexpected failure value"; } TEST(SimplePackedSerializationTest, SerializeExpectedFailure) { auto B = spsSerialize>>( toSPSSerializableExpected( make_error("test error message"))); if (!B) { ADD_FAILURE() << "Unexpected failure to serialize expected-failure value"; return; } SPSSerializableExpected SE; if (!spsDeserialize>>(*B, SE)) { ADD_FAILURE() << "Unexpected failure to deserialize expected-failure value"; return; } auto E = SE.toExpected(); if (E) ADD_FAILURE() << "Unexpected failure value"; else EXPECT_EQ(toString(E.takeError()), std::string("test error message")); }