blob: 86b0815078698bf9c81b6079ac2a0fab6193d8a6 [file] [edit]
// Copyright 2026 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 "quiche/common/quiche_checked_math.h"
#include <cstdint>
#include <limits>
#include <optional>
#include "quiche/common/platform/api/quiche_test.h"
namespace quiche {
namespace {
template <typename Int>
void RunAddTests() {
constexpr Int kMax = std::numeric_limits<Int>::max();
EXPECT_EQ(SafeAdd<Int>(0, 0), 0);
EXPECT_EQ(SafeAdd<Int>(2, 2), 4);
EXPECT_EQ(SafeAdd<Int>(kMax - 1, 1), kMax);
EXPECT_EQ(SafeAdd<Int>(kMax, 0), kMax);
EXPECT_EQ(SafeAdd<Int>(kMax - 1, 2), std::nullopt);
EXPECT_EQ(SafeAdd<Int>(kMax, 1), std::nullopt);
EXPECT_EQ(SafeAdd<Int>(kMax, kMax), std::nullopt);
}
TEST(QuicheCheckedMathTest, Add) {
// Spell out uint8_t tests explicitly to make them easier to follow.
EXPECT_EQ(SafeAdd<uint8_t>(0, 0), 0);
EXPECT_EQ(SafeAdd<uint8_t>(2, 2), 4);
EXPECT_EQ(SafeAdd<uint8_t>(254, 1), 255);
EXPECT_EQ(SafeAdd<uint8_t>(255, 0), 255);
EXPECT_EQ(SafeAdd<uint8_t>(254, 2), std::nullopt);
EXPECT_EQ(SafeAdd<uint8_t>(255, 1), std::nullopt);
EXPECT_EQ(SafeAdd<uint8_t>(255, 255), std::nullopt);
// Run the remainder of tests through a templated function.
RunAddTests<uint16_t>();
RunAddTests<uint32_t>();
RunAddTests<uint64_t>();
}
template <typename Int>
void RunIncrementTests() {
constexpr Int kMax = std::numeric_limits<Int>::max();
Int var = kMax - 5;
EXPECT_TRUE(SafeIncrementBy<Int>(var, 0));
EXPECT_EQ(var, kMax - 5);
EXPECT_TRUE(SafeIncrementBy<Int>(var, 5));
EXPECT_EQ(var, kMax);
EXPECT_FALSE(SafeIncrementBy<Int>(var, 1));
EXPECT_EQ(var, kMax);
}
TEST(QuicheCheckedMathTest, IncrementBy) {
// Spell out uint8_t tests explicitly to make them easier to follow.
uint8_t var8 = 250;
EXPECT_TRUE(SafeIncrementBy<uint8_t>(var8, 0));
EXPECT_EQ(var8, 250);
EXPECT_TRUE(SafeIncrementBy<uint8_t>(var8, 2));
EXPECT_EQ(var8, 252);
EXPECT_TRUE(SafeIncrementBy<uint8_t>(var8, 3));
EXPECT_EQ(var8, 255);
EXPECT_FALSE(SafeIncrementBy<uint8_t>(var8, 1));
EXPECT_EQ(var8, 255);
EXPECT_FALSE(SafeIncrementBy<uint8_t>(var8, 255));
EXPECT_EQ(var8, 255);
// Run the remainder of tests through a templated function.
RunIncrementTests<uint16_t>();
RunIncrementTests<uint32_t>();
RunIncrementTests<uint64_t>();
}
TEST(QuicheCheckedMathTest, Sum) {
EXPECT_EQ(SafeSum<uint8_t>({}), 0);
EXPECT_EQ(SafeSum<uint8_t>({2, 2}), 4);
EXPECT_EQ(SafeSum<uint8_t>({1, 2, 3}), 6);
EXPECT_EQ(SafeSum<uint8_t>({200, 200}), std::nullopt);
EXPECT_EQ(SafeSum<uint8_t>({200, 200, 200}), std::nullopt);
EXPECT_EQ(SafeSum<uint8_t>({100, 100, 100}), std::nullopt);
EXPECT_EQ(SafeSum<uint8_t>({128, 126, 1}), 255);
EXPECT_EQ(SafeSum<uint8_t>({128, 126, 2}), std::nullopt);
}
} // namespace
} // namespace quiche