blob: 4ba8d253cd1610b5b1ca7acb3d5e4c5897fcd98f [file] [edit]
// Copyright 2026 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "proto.h"
#include "proto_reader.h"
#include "input_stream.h"
#include "output_stream.h"
#include "test.h"
#include <string>
#include <vector>
#include <limits>
TEST(ProtoTest, Varint32RoundTrip) {
std::vector<uint32_t> values = {0, 1, 127, 128, 300, 0x7FFFFFFF, 0xFFFFFFFF};
for (uint32_t val : values) {
StringOutputStream out;
WriteVarint32NoTag(&out, val);
uint32_t read_val;
const std::string& buf = out.str();
MemoryInputStream in(buf.data(), buf.size());
EXPECT_TRUE(ReadVarint32(in, &read_val));
EXPECT_EQ(val, read_val);
}
}
TEST(ProtoTest, Varint64RoundTrip) {
std::vector<uint64_t> values = {0, 1, 127, 128, 300, 0x7FFFFFFF, 0xFFFFFFFF,
0x100000000ULL, 0x7FFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL};
for (uint64_t val : values) {
StringOutputStream out;
WriteVarint64(&out, 1, val);
uint32_t tag;
int field_number, wire_type;
uint64_t read_val;
const std::string& buf = out.str();
MemoryInputStream in(buf.data(), buf.size());
EXPECT_TRUE(ReadTag(in, &tag, &field_number, &wire_type));
EXPECT_EQ(1, field_number);
EXPECT_EQ(0, wire_type);
EXPECT_TRUE(ReadVarint64(in, &read_val));
EXPECT_EQ(val, read_val);
}
}
TEST(ProtoTest, Fixed32RoundTrip) {
std::vector<uint32_t> values = {0, 1, 0x12345678, 0xFFFFFFFF};
for (uint32_t val : values) {
StringOutputStream out;
WriteFixed32NoTag(&out, val);
uint32_t read_val;
const std::string& buf = out.str();
MemoryInputStream in(buf.data(), buf.size());
EXPECT_TRUE(ReadFixed32(in, &read_val));
EXPECT_EQ(val, read_val);
}
}
TEST(ProtoTest, Fixed64RoundTrip) {
std::vector<uint64_t> values = {0, 1, 0x123456789ABCDEF0ULL, 0xFFFFFFFFFFFFFFFFULL};
for (uint64_t val : values) {
StringOutputStream out;
WriteFixed64NoTag(&out, val);
uint64_t read_val;
const std::string& buf = out.str();
MemoryInputStream in(buf.data(), buf.size());
EXPECT_TRUE(ReadFixed64(in, &read_val));
EXPECT_EQ(val, read_val);
}
}
TEST(ProtoTest, StringRoundTrip) {
std::vector<std::string> values = {"", "a", "hello", std::string(300, 'x')};
for (const auto& val : values) {
StringOutputStream out;
WriteString(&out, 1, val);
uint32_t tag;
int field_number, wire_type;
std::string read_val;
const std::string& buf = out.str();
MemoryInputStream in(buf.data(), buf.size());
EXPECT_TRUE(ReadTag(in, &tag, &field_number, &wire_type));
EXPECT_EQ(1, field_number);
EXPECT_EQ(2, wire_type);
EXPECT_TRUE(ReadString(in, &read_val));
EXPECT_EQ(val, read_val);
}
}
TEST(ProtoTest, ZigZag32RoundTrip) {
std::vector<int32_t> values = {0, 1, -1, 127, -128, 0x7FFFFFFF, (int32_t)0x80000000};
for (int32_t val : values) {
uint32_t encoded = ZigZagEncode32(val);
int32_t decoded = ZigZagDecode32(encoded);
EXPECT_EQ(val, decoded);
}
}
TEST(ProtoTest, ZigZag64RoundTrip) {
std::vector<int64_t> values = {0, 1, -1, 127, -128, 0x7FFFFFFFFFFFFFFFULL, (int64_t)0x8000000000000000ULL};
for (int64_t val : values) {
uint64_t encoded = ZigZagEncode64(val);
int64_t decoded = ZigZagDecode64(encoded);
EXPECT_EQ(val, decoded);
}
}
TEST(ProtoTest, LargeFieldNumbers) {
std::vector<int> field_numbers = {1, 15, 16, 31, 32, 1000, 0x1FFFFFFF};
for (int fn : field_numbers) {
StringOutputStream out;
WriteVarint32(&out, fn, 42);
uint32_t tag;
int read_fn, wire_type;
uint32_t read_val;
const std::string& buf = out.str();
MemoryInputStream in(buf.data(), buf.size());
EXPECT_TRUE(ReadTag(in, &tag, &read_fn, &wire_type));
EXPECT_EQ(fn, read_fn);
EXPECT_EQ(0, wire_type);
EXPECT_TRUE(ReadVarint32(in, &read_val));
EXPECT_EQ(42, read_val);
}
}
TEST(ProtoTest, LargeVarints) {
// Specifically test values with bit 31 set to catch signedness/truncation issues.
std::vector<uint64_t> values = {
0x80000000ULL, // bit 31 set
0xFFFFFFFFULL, // all 32 bits set
0x100000000ULL, // bit 32 set
0x7FFFFFFFFFFFFFFFULL, // max int64
0xFFFFFFFFFFFFFFFFULL // max uint64
};
for (uint64_t val : values) {
StringOutputStream out;
WriteVarint64(&out, 1, val);
uint64_t read_val;
const std::string& buf = out.str();
MemoryInputStream in(buf.data(), buf.size());
uint32_t tag;
int fn, wt;
ASSERT_TRUE(ReadTag(in, &tag, &fn, &wt));
EXPECT_TRUE(ReadVarint64(in, &read_val));
EXPECT_EQ(val, read_val);
}
// Test 32-bit varint with bit 31 set
uint32_t val32 = 0x80000000U;
StringOutputStream out;
WriteVarint32NoTag(&out, val32);
uint32_t read_val32;
MemoryInputStream in(out.str().data(), out.str().size());
EXPECT_TRUE(ReadVarint32(in, &read_val32));
EXPECT_EQ(val32, read_val32);
}