Skip to content

Commit de9faf8

Browse files
author
Yash Chauhan
committed
Added tests for unpacked repeated fields
1 parent 89c2d96 commit de9faf8

File tree

1 file changed

+381
-0
lines changed

1 file changed

+381
-0
lines changed

tests/unit/lv_message_tests.cc

Lines changed: 381 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1876,6 +1876,387 @@ TEST_F(StressTest, LargeRepeatedField)
18761876
}
18771877
}
18781878

1879+
// =====================================================================
1880+
// Packed and unpacked repeated field parse tests
1881+
// Wire bytes are built manually to exercise each encoding path directly.
1882+
// The existing RepeatedRoundTripTest suite always serializes packed (proto3
1883+
// default). These tests feed raw unpacked wire to verify the new unpacked
1884+
// path, and mixed (packed-first) wire to verify both encodings accumulate
1885+
// into the same field.
1886+
// =====================================================================
1887+
1888+
// Additional wire-building helpers for repeated fields.
1889+
1890+
// N separate (tag, varint64) pairs — unpacked repeated varint.
1891+
static std::string MakeUnpackedVarintRepeated(int field_number, const std::vector<uint64_t>& values)
1892+
{
1893+
std::string out;
1894+
for (uint64_t v : values) out += MakeVarintField(field_number, v);
1895+
return out;
1896+
}
1897+
1898+
// Single (tag, length, varints…) — packed repeated varint.
1899+
static std::string MakePackedVarintRepeated(int field_number, const std::vector<uint64_t>& values)
1900+
{
1901+
std::string payload;
1902+
{
1903+
google::protobuf::io::StringOutputStream sos(&payload);
1904+
google::protobuf::io::CodedOutputStream cos(&sos);
1905+
for (uint64_t v : values) cos.WriteVarint64(v);
1906+
}
1907+
return MakeLenDelimField(field_number, payload);
1908+
}
1909+
1910+
// N separate fixed32 tags — unpacked repeated fixed32.
1911+
static std::string MakeUnpackedFixed32Repeated(int field_number, const std::vector<uint32_t>& values)
1912+
{
1913+
std::string out;
1914+
for (uint32_t v : values) out += MakeFixed32Field(field_number, v);
1915+
return out;
1916+
}
1917+
1918+
// Single packed repeated fixed32.
1919+
static std::string MakePackedFixed32Repeated(int field_number, const std::vector<uint32_t>& values)
1920+
{
1921+
std::string payload;
1922+
{
1923+
google::protobuf::io::StringOutputStream sos(&payload);
1924+
google::protobuf::io::CodedOutputStream cos(&sos);
1925+
for (uint32_t v : values) cos.WriteLittleEndian32(v);
1926+
}
1927+
return MakeLenDelimField(field_number, payload);
1928+
}
1929+
1930+
// N separate fixed64 tags — unpacked repeated fixed64.
1931+
static std::string MakeUnpackedFixed64Repeated(int field_number, const std::vector<uint64_t>& values)
1932+
{
1933+
std::string out;
1934+
for (uint64_t v : values) out += MakeFixed64Field(field_number, v);
1935+
return out;
1936+
}
1937+
1938+
// Single packed repeated fixed64.
1939+
static std::string MakePackedFixed64Repeated(int field_number, const std::vector<uint64_t>& values)
1940+
{
1941+
std::string payload;
1942+
{
1943+
google::protobuf::io::StringOutputStream sos(&payload);
1944+
google::protobuf::io::CodedOutputStream cos(&sos);
1945+
for (uint64_t v : values) cos.WriteLittleEndian64(v);
1946+
}
1947+
return MakeLenDelimField(field_number, payload);
1948+
}
1949+
1950+
class PackedUnpackedTest : public ::testing::Test {};
1951+
1952+
// ---- Unpacked: all 14 scalar types ----
1953+
1954+
TEST_F(PackedUnpackedTest, Unpacked_Int32)
1955+
{
1956+
auto meta = MakeSingleFieldMetadata(1, LVMessageMetadataType::Int32Value, true);
1957+
std::string wire = MakeUnpackedVarintRepeated(1, {10, 20, 30});
1958+
std::cout << " [wire] " << wire.size() << " byte(s):\n" << HexDump(wire);
1959+
1960+
LVMessage msg(meta);
1961+
ASSERT_TRUE(msg.ParseFromString(wire));
1962+
auto vals = GetRepeatedValue<int>(msg, 1);
1963+
ASSERT_EQ(vals.size(), 3u);
1964+
EXPECT_EQ(vals[0], 10);
1965+
EXPECT_EQ(vals[1], 20);
1966+
EXPECT_EQ(vals[2], 30);
1967+
}
1968+
1969+
TEST_F(PackedUnpackedTest, Unpacked_Int64)
1970+
{
1971+
auto meta = MakeSingleFieldMetadata(1, LVMessageMetadataType::Int64Value, true);
1972+
std::string wire = MakeUnpackedVarintRepeated(1, {
1973+
static_cast<uint64_t>(1000000000000LL),
1974+
static_cast<uint64_t>(2000000000000LL)});
1975+
std::cout << " [wire] " << wire.size() << " byte(s):\n" << HexDump(wire);
1976+
1977+
LVMessage msg(meta);
1978+
ASSERT_TRUE(msg.ParseFromString(wire));
1979+
auto vals = GetRepeatedValue<int64_t>(msg, 1);
1980+
ASSERT_EQ(vals.size(), 2u);
1981+
EXPECT_EQ(vals[0], 1000000000000LL);
1982+
EXPECT_EQ(vals[1], 2000000000000LL);
1983+
}
1984+
1985+
TEST_F(PackedUnpackedTest, Unpacked_UInt32)
1986+
{
1987+
auto meta = MakeSingleFieldMetadata(1, LVMessageMetadataType::UInt32Value, true);
1988+
std::string wire = MakeUnpackedVarintRepeated(1, {100u, 200u, 300u});
1989+
std::cout << " [wire] " << wire.size() << " byte(s):\n" << HexDump(wire);
1990+
1991+
LVMessage msg(meta);
1992+
ASSERT_TRUE(msg.ParseFromString(wire));
1993+
auto vals = GetRepeatedValue<uint32_t>(msg, 1);
1994+
ASSERT_EQ(vals.size(), 3u);
1995+
EXPECT_EQ(vals[0], 100u);
1996+
EXPECT_EQ(vals[1], 200u);
1997+
EXPECT_EQ(vals[2], 300u);
1998+
}
1999+
2000+
TEST_F(PackedUnpackedTest, Unpacked_UInt64)
2001+
{
2002+
auto meta = MakeSingleFieldMetadata(1, LVMessageMetadataType::UInt64Value, true);
2003+
std::string wire = MakeUnpackedVarintRepeated(1, {1000u, 2000u, 3000u});
2004+
std::cout << " [wire] " << wire.size() << " byte(s):\n" << HexDump(wire);
2005+
2006+
LVMessage msg(meta);
2007+
ASSERT_TRUE(msg.ParseFromString(wire));
2008+
auto vals = GetRepeatedValue<uint64_t>(msg, 1);
2009+
ASSERT_EQ(vals.size(), 3u);
2010+
EXPECT_EQ(vals[0], 1000ULL);
2011+
EXPECT_EQ(vals[1], 2000ULL);
2012+
EXPECT_EQ(vals[2], 3000ULL);
2013+
}
2014+
2015+
TEST_F(PackedUnpackedTest, Unpacked_Bool)
2016+
{
2017+
auto meta = MakeSingleFieldMetadata(1, LVMessageMetadataType::BoolValue, true);
2018+
std::string wire = MakeUnpackedVarintRepeated(1, {1, 0, 1}); // true, false, true
2019+
std::cout << " [wire] " << wire.size() << " byte(s):\n" << HexDump(wire);
2020+
2021+
LVMessage msg(meta);
2022+
ASSERT_TRUE(msg.ParseFromString(wire));
2023+
auto vals = GetRepeatedValue<bool>(msg, 1);
2024+
ASSERT_EQ(vals.size(), 3u);
2025+
EXPECT_EQ(vals[0], true);
2026+
EXPECT_EQ(vals[1], false);
2027+
EXPECT_EQ(vals[2], true);
2028+
}
2029+
2030+
TEST_F(PackedUnpackedTest, Unpacked_Enum)
2031+
{
2032+
auto meta = MakeSingleFieldMetadata(1, LVMessageMetadataType::EnumValue, true);
2033+
std::string wire = MakeUnpackedVarintRepeated(1, {0, 1, 2});
2034+
std::cout << " [wire] " << wire.size() << " byte(s):\n" << HexDump(wire);
2035+
2036+
LVMessage msg(meta);
2037+
ASSERT_TRUE(msg.ParseFromString(wire));
2038+
auto vals = GetRepeatedValue<int>(msg, 1);
2039+
ASSERT_EQ(vals.size(), 3u);
2040+
EXPECT_EQ(vals[0], 0);
2041+
EXPECT_EQ(vals[1], 1);
2042+
EXPECT_EQ(vals[2], 2);
2043+
}
2044+
2045+
TEST_F(PackedUnpackedTest, Unpacked_SInt32)
2046+
{
2047+
using WFL = google::protobuf::internal::WireFormatLite;
2048+
auto meta = MakeSingleFieldMetadata(1, LVMessageMetadataType::SInt32Value, true);
2049+
// Zigzag-encode the values before putting them on the wire.
2050+
std::string wire = MakeUnpackedVarintRepeated(1, {
2051+
WFL::ZigZagEncode32(-1),
2052+
WFL::ZigZagEncode32(1),
2053+
WFL::ZigZagEncode32(-100)});
2054+
std::cout << " [wire] " << wire.size() << " byte(s):\n" << HexDump(wire);
2055+
2056+
LVMessage msg(meta);
2057+
ASSERT_TRUE(msg.ParseFromString(wire));
2058+
auto vals = GetRepeatedValue<int32_t>(msg, 1);
2059+
ASSERT_EQ(vals.size(), 3u);
2060+
EXPECT_EQ(vals[0], -1);
2061+
EXPECT_EQ(vals[1], 1);
2062+
EXPECT_EQ(vals[2], -100);
2063+
}
2064+
2065+
TEST_F(PackedUnpackedTest, Unpacked_SInt64)
2066+
{
2067+
using WFL = google::protobuf::internal::WireFormatLite;
2068+
auto meta = MakeSingleFieldMetadata(1, LVMessageMetadataType::SInt64Value, true);
2069+
std::string wire = MakeUnpackedVarintRepeated(1, {
2070+
WFL::ZigZagEncode64(-1LL),
2071+
WFL::ZigZagEncode64(1LL),
2072+
WFL::ZigZagEncode64(-1000000000000LL)});
2073+
std::cout << " [wire] " << wire.size() << " byte(s):\n" << HexDump(wire);
2074+
2075+
LVMessage msg(meta);
2076+
ASSERT_TRUE(msg.ParseFromString(wire));
2077+
auto vals = GetRepeatedValue<int64_t>(msg, 1);
2078+
ASSERT_EQ(vals.size(), 3u);
2079+
EXPECT_EQ(vals[0], -1LL);
2080+
EXPECT_EQ(vals[1], 1LL);
2081+
EXPECT_EQ(vals[2], -1000000000000LL);
2082+
}
2083+
2084+
TEST_F(PackedUnpackedTest, Unpacked_Float)
2085+
{
2086+
auto meta = MakeSingleFieldMetadata(1, LVMessageMetadataType::FloatValue, true);
2087+
float f0 = 1.5f, f1 = -2.5f, f2 = 0.0f;
2088+
uint32_t u0, u1, u2;
2089+
memcpy(&u0, &f0, 4); memcpy(&u1, &f1, 4); memcpy(&u2, &f2, 4);
2090+
std::string wire = MakeUnpackedFixed32Repeated(1, {u0, u1, u2});
2091+
std::cout << " [wire] " << wire.size() << " byte(s):\n" << HexDump(wire);
2092+
2093+
LVMessage msg(meta);
2094+
ASSERT_TRUE(msg.ParseFromString(wire));
2095+
auto vals = GetRepeatedValue<float>(msg, 1);
2096+
ASSERT_EQ(vals.size(), 3u);
2097+
EXPECT_FLOAT_EQ(vals[0], 1.5f);
2098+
EXPECT_FLOAT_EQ(vals[1], -2.5f);
2099+
EXPECT_FLOAT_EQ(vals[2], 0.0f);
2100+
}
2101+
2102+
TEST_F(PackedUnpackedTest, Unpacked_Double)
2103+
{
2104+
auto meta = MakeSingleFieldMetadata(1, LVMessageMetadataType::DoubleValue, true);
2105+
double d0 = 3.14, d1 = -2.718;
2106+
uint64_t u0, u1;
2107+
memcpy(&u0, &d0, 8); memcpy(&u1, &d1, 8);
2108+
std::string wire = MakeUnpackedFixed64Repeated(1, {u0, u1});
2109+
std::cout << " [wire] " << wire.size() << " byte(s):\n" << HexDump(wire);
2110+
2111+
LVMessage msg(meta);
2112+
ASSERT_TRUE(msg.ParseFromString(wire));
2113+
auto vals = GetRepeatedValue<double>(msg, 1);
2114+
ASSERT_EQ(vals.size(), 2u);
2115+
EXPECT_DOUBLE_EQ(vals[0], 3.14);
2116+
EXPECT_DOUBLE_EQ(vals[1], -2.718);
2117+
}
2118+
2119+
TEST_F(PackedUnpackedTest, Unpacked_Fixed32)
2120+
{
2121+
auto meta = MakeSingleFieldMetadata(1, LVMessageMetadataType::Fixed32Value, true);
2122+
std::string wire = MakeUnpackedFixed32Repeated(1, {0xDEADBEEFu, 42u, 0u});
2123+
std::cout << " [wire] " << wire.size() << " byte(s):\n" << HexDump(wire);
2124+
2125+
LVMessage msg(meta);
2126+
ASSERT_TRUE(msg.ParseFromString(wire));
2127+
auto vals = GetRepeatedValue<uint32_t>(msg, 1);
2128+
ASSERT_EQ(vals.size(), 3u);
2129+
EXPECT_EQ(vals[0], 0xDEADBEEFu);
2130+
EXPECT_EQ(vals[1], 42u);
2131+
EXPECT_EQ(vals[2], 0u);
2132+
}
2133+
2134+
TEST_F(PackedUnpackedTest, Unpacked_Fixed64)
2135+
{
2136+
auto meta = MakeSingleFieldMetadata(1, LVMessageMetadataType::Fixed64Value, true);
2137+
std::string wire = MakeUnpackedFixed64Repeated(1, {0xDEADBEEFCAFEBABEULL, 0ULL});
2138+
std::cout << " [wire] " << wire.size() << " byte(s):\n" << HexDump(wire);
2139+
2140+
LVMessage msg(meta);
2141+
ASSERT_TRUE(msg.ParseFromString(wire));
2142+
auto vals = GetRepeatedValue<uint64_t>(msg, 1);
2143+
ASSERT_EQ(vals.size(), 2u);
2144+
EXPECT_EQ(vals[0], 0xDEADBEEFCAFEBABEULL);
2145+
EXPECT_EQ(vals[1], 0ULL);
2146+
}
2147+
2148+
TEST_F(PackedUnpackedTest, Unpacked_SFixed32)
2149+
{
2150+
auto meta = MakeSingleFieldMetadata(1, LVMessageMetadataType::SFixed32Value, true);
2151+
int32_t v0 = -12345, v1 = 67890;
2152+
std::string wire = MakeUnpackedFixed32Repeated(1, {
2153+
static_cast<uint32_t>(v0), static_cast<uint32_t>(v1)});
2154+
std::cout << " [wire] " << wire.size() << " byte(s):\n" << HexDump(wire);
2155+
2156+
LVMessage msg(meta);
2157+
ASSERT_TRUE(msg.ParseFromString(wire));
2158+
auto vals = GetRepeatedValue<int32_t>(msg, 1);
2159+
ASSERT_EQ(vals.size(), 2u);
2160+
EXPECT_EQ(vals[0], -12345);
2161+
EXPECT_EQ(vals[1], 67890);
2162+
}
2163+
2164+
TEST_F(PackedUnpackedTest, Unpacked_SFixed64)
2165+
{
2166+
auto meta = MakeSingleFieldMetadata(1, LVMessageMetadataType::SFixed64Value, true);
2167+
int64_t v0 = -9876543210LL, v1 = 1234567890LL;
2168+
std::string wire = MakeUnpackedFixed64Repeated(1, {
2169+
static_cast<uint64_t>(v0), static_cast<uint64_t>(v1)});
2170+
std::cout << " [wire] " << wire.size() << " byte(s):\n" << HexDump(wire);
2171+
2172+
LVMessage msg(meta);
2173+
ASSERT_TRUE(msg.ParseFromString(wire));
2174+
auto vals = GetRepeatedValue<int64_t>(msg, 1);
2175+
ASSERT_EQ(vals.size(), 2u);
2176+
EXPECT_EQ(vals[0], -9876543210LL);
2177+
EXPECT_EQ(vals[1], 1234567890LL);
2178+
}
2179+
2180+
// ---- Mixed: packed batch first, then individual unpacked elements ----
2181+
// The protobuf spec allows mixing both encodings for the same repeated field.
2182+
// The packed path creates the entry; the unpacked path finds and appends to it.
2183+
2184+
TEST_F(PackedUnpackedTest, Mixed_PackedThenUnpacked_Int32)
2185+
{
2186+
auto meta = MakeSingleFieldMetadata(1, LVMessageMetadataType::Int32Value, true);
2187+
// Packed batch [1, 2, 3], then two unpacked elements 4 and 5.
2188+
std::string wire = MakePackedVarintRepeated(1, {1, 2, 3})
2189+
+ MakeUnpackedVarintRepeated(1, {4, 5});
2190+
std::cout << " [wire] " << wire.size() << " byte(s):\n" << HexDump(wire);
2191+
2192+
LVMessage msg(meta);
2193+
ASSERT_TRUE(msg.ParseFromString(wire));
2194+
auto vals = GetRepeatedValue<int>(msg, 1);
2195+
ASSERT_EQ(vals.size(), 5u);
2196+
EXPECT_EQ(vals[0], 1);
2197+
EXPECT_EQ(vals[1], 2);
2198+
EXPECT_EQ(vals[2], 3);
2199+
EXPECT_EQ(vals[3], 4);
2200+
EXPECT_EQ(vals[4], 5);
2201+
}
2202+
2203+
TEST_F(PackedUnpackedTest, Mixed_PackedThenUnpacked_Float)
2204+
{
2205+
auto meta = MakeSingleFieldMetadata(1, LVMessageMetadataType::FloatValue, true);
2206+
float f0 = 1.0f, f1 = 2.0f, f2 = 3.0f;
2207+
uint32_t u0, u1, u2;
2208+
memcpy(&u0, &f0, 4); memcpy(&u1, &f1, 4); memcpy(&u2, &f2, 4);
2209+
// Packed [1.0, 2.0], then unpacked 3.0.
2210+
std::string wire = MakePackedFixed32Repeated(1, {u0, u1})
2211+
+ MakeUnpackedFixed32Repeated(1, {u2});
2212+
std::cout << " [wire] " << wire.size() << " byte(s):\n" << HexDump(wire);
2213+
2214+
LVMessage msg(meta);
2215+
ASSERT_TRUE(msg.ParseFromString(wire));
2216+
auto vals = GetRepeatedValue<float>(msg, 1);
2217+
ASSERT_EQ(vals.size(), 3u);
2218+
EXPECT_FLOAT_EQ(vals[0], 1.0f);
2219+
EXPECT_FLOAT_EQ(vals[1], 2.0f);
2220+
EXPECT_FLOAT_EQ(vals[2], 3.0f);
2221+
}
2222+
2223+
TEST_F(PackedUnpackedTest, Mixed_PackedThenUnpacked_Double)
2224+
{
2225+
auto meta = MakeSingleFieldMetadata(1, LVMessageMetadataType::DoubleValue, true);
2226+
double d0 = 1.0, d1 = 2.0, d2 = 3.0;
2227+
uint64_t u0, u1, u2;
2228+
memcpy(&u0, &d0, 8); memcpy(&u1, &d1, 8); memcpy(&u2, &d2, 8);
2229+
std::string wire = MakePackedFixed64Repeated(1, {u0, u1})
2230+
+ MakeUnpackedFixed64Repeated(1, {u2});
2231+
std::cout << " [wire] " << wire.size() << " byte(s):\n" << HexDump(wire);
2232+
2233+
LVMessage msg(meta);
2234+
ASSERT_TRUE(msg.ParseFromString(wire));
2235+
auto vals = GetRepeatedValue<double>(msg, 1);
2236+
ASSERT_EQ(vals.size(), 3u);
2237+
EXPECT_DOUBLE_EQ(vals[0], 1.0);
2238+
EXPECT_DOUBLE_EQ(vals[1], 2.0);
2239+
EXPECT_DOUBLE_EQ(vals[2], 3.0);
2240+
}
2241+
2242+
TEST_F(PackedUnpackedTest, Mixed_PackedThenUnpacked_SInt32)
2243+
{
2244+
using WFL = google::protobuf::internal::WireFormatLite;
2245+
auto meta = MakeSingleFieldMetadata(1, LVMessageMetadataType::SInt32Value, true);
2246+
// Packed batch [-1, 0], then unpacked 1.
2247+
std::string wire = MakePackedVarintRepeated(1, {WFL::ZigZagEncode32(-1), WFL::ZigZagEncode32(0)})
2248+
+ MakeUnpackedVarintRepeated(1, {WFL::ZigZagEncode32(1)});
2249+
std::cout << " [wire] " << wire.size() << " byte(s):\n" << HexDump(wire);
2250+
2251+
LVMessage msg(meta);
2252+
ASSERT_TRUE(msg.ParseFromString(wire));
2253+
auto vals = GetRepeatedValue<int32_t>(msg, 1);
2254+
ASSERT_EQ(vals.size(), 3u);
2255+
EXPECT_EQ(vals[0], -1);
2256+
EXPECT_EQ(vals[1], 0);
2257+
EXPECT_EQ(vals[2], 1);
2258+
}
2259+
18792260
// =====================================================================
18802261
// main
18812262
// =====================================================================

0 commit comments

Comments
 (0)