blob: f3d2bbbdafea445918d83bff6a11b18648afdc0f [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "net/quic/quic_data_writer.h"
#include <stdint.h>
#include <memory>
#include "net/quic/quic_data_reader.h"
#include "net/test/gtest_util.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
namespace test {
namespace {
TEST(QuicDataWriterTest, SanityCheckUFloat16Consts) {
// Check the arithmetic on the constants - otherwise the values below make
// no sense.
EXPECT_EQ(30, kUFloat16MaxExponent);
EXPECT_EQ(11, kUFloat16MantissaBits);
EXPECT_EQ(12, kUFloat16MantissaEffectiveBits);
EXPECT_EQ(UINT64_C(0x3FFC0000000), kUFloat16MaxValue);
}
TEST(QuicDataWriterTest, WriteUFloat16) {
struct TestCase {
uint64_t decoded;
uint16_t encoded;
};
TestCase test_cases[] = {
// Small numbers represent themselves.
{0, 0},
{1, 1},
{2, 2},
{3, 3},
{4, 4},
{5, 5},
{6, 6},
{7, 7},
{15, 15},
{31, 31},
{42, 42},
{123, 123},
{1234, 1234},
// Check transition through 2^11.
{2046, 2046},
{2047, 2047},
{2048, 2048},
{2049, 2049},
// Running out of mantissa at 2^12.
{4094, 4094},
{4095, 4095},
{4096, 4096},
{4097, 4096},
{4098, 4097},
{4099, 4097},
{4100, 4098},
{4101, 4098},
// Check transition through 2^13.
{8190, 6143},
{8191, 6143},
{8192, 6144},
{8193, 6144},
{8194, 6144},
{8195, 6144},
{8196, 6145},
{8197, 6145},
// Half-way through the exponents.
{0x7FF8000, 0x87FF},
{0x7FFFFFF, 0x87FF},
{0x8000000, 0x8800},
{0xFFF0000, 0x8FFF},
{0xFFFFFFF, 0x8FFF},
{0x10000000, 0x9000},
// Transition into the largest exponent.
{0x1FFFFFFFFFE, 0xF7FF},
{0x1FFFFFFFFFF, 0xF7FF},
{0x20000000000, 0xF800},
{0x20000000001, 0xF800},
{0x2003FFFFFFE, 0xF800},
{0x2003FFFFFFF, 0xF800},
{0x20040000000, 0xF801},
{0x20040000001, 0xF801},
// Transition into the max value and clamping.
{0x3FF80000000, 0xFFFE},
{0x3FFBFFFFFFF, 0xFFFE},
{0x3FFC0000000, 0xFFFF},
{0x3FFC0000001, 0xFFFF},
{0x3FFFFFFFFFF, 0xFFFF},
{0x40000000000, 0xFFFF},
{0xFFFFFFFFFFFFFFFF, 0xFFFF},
};
int num_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
for (int i = 0; i < num_test_cases; ++i) {
char buffer[2];
QuicDataWriter writer(2, buffer);
EXPECT_TRUE(writer.WriteUFloat16(test_cases[i].decoded));
EXPECT_EQ(test_cases[i].encoded,
*reinterpret_cast<uint16_t*>(writer.data()));
}
}
TEST(QuicDataWriterTest, ReadUFloat16) {
struct TestCase {
uint64_t decoded;
uint16_t encoded;
};
TestCase test_cases[] = {
// There are fewer decoding test cases because encoding truncates, and
// decoding returns the smallest expansion.
// Small numbers represent themselves.
{0, 0},
{1, 1},
{2, 2},
{3, 3},
{4, 4},
{5, 5},
{6, 6},
{7, 7},
{15, 15},
{31, 31},
{42, 42},
{123, 123},
{1234, 1234},
// Check transition through 2^11.
{2046, 2046},
{2047, 2047},
{2048, 2048},
{2049, 2049},
// Running out of mantissa at 2^12.
{4094, 4094},
{4095, 4095},
{4096, 4096},
{4098, 4097},
{4100, 4098},
// Check transition through 2^13.
{8190, 6143},
{8192, 6144},
{8196, 6145},
// Half-way through the exponents.
{0x7FF8000, 0x87FF},
{0x8000000, 0x8800},
{0xFFF0000, 0x8FFF},
{0x10000000, 0x9000},
// Transition into the largest exponent.
{0x1FFE0000000, 0xF7FF},
{0x20000000000, 0xF800},
{0x20040000000, 0xF801},
// Transition into the max value.
{0x3FF80000000, 0xFFFE},
{0x3FFC0000000, 0xFFFF},
};
int num_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
for (int i = 0; i < num_test_cases; ++i) {
QuicDataReader reader(reinterpret_cast<char*>(&test_cases[i].encoded), 2);
uint64_t value;
EXPECT_TRUE(reader.ReadUFloat16(&value));
EXPECT_EQ(test_cases[i].decoded, value);
}
}
TEST(QuicDataWriterTest, RoundTripUFloat16) {
// Just test all 16-bit encoded values. 0 and max already tested above.
uint64_t previous_value = 0;
for (uint16_t i = 1; i < 0xFFFF; ++i) {
// Read the two bytes.
QuicDataReader reader(reinterpret_cast<char*>(&i), 2);
uint64_t value;
// All values must be decodable.
EXPECT_TRUE(reader.ReadUFloat16(&value));
// Check that small numbers represent themselves
if (i < 4097)
EXPECT_EQ(i, value);
// Check there's monotonic growth.
EXPECT_LT(previous_value, value);
// Check that precision is within 0.5% away from the denormals.
if (i > 2000)
EXPECT_GT(previous_value * 1005, value * 1000);
// Check we're always within the promised range.
EXPECT_LT(value, UINT64_C(0x3FFC0000000));
previous_value = value;
char buffer[6];
QuicDataWriter writer(6, buffer);
EXPECT_TRUE(writer.WriteUFloat16(value - 1));
EXPECT_TRUE(writer.WriteUFloat16(value));
EXPECT_TRUE(writer.WriteUFloat16(value + 1));
// Check minimal decoding (previous decoding has previous encoding).
EXPECT_EQ(i - 1, *reinterpret_cast<uint16_t*>(writer.data()));
// Check roundtrip.
EXPECT_EQ(i, *reinterpret_cast<uint16_t*>(writer.data() + 2));
// Check next decoding.
EXPECT_EQ(i < 4096 ? i + 1 : i,
*reinterpret_cast<uint16_t*>(writer.data() + 4));
}
}
} // namespace
} // namespace test
} // namespace net