You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
363 lines
12 KiB
363 lines
12 KiB
// Copyright 2019 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 "util/saturate_cast.h"
|
|
|
|
#include "gtest/gtest.h"
|
|
|
|
namespace openscreen {
|
|
namespace {
|
|
|
|
TEST(SaturateCastTest, LargerToSmallerSignedInteger) {
|
|
struct ValuePair {
|
|
int64_t from;
|
|
int32_t to;
|
|
};
|
|
constexpr ValuePair kValuePairs[] = {
|
|
{std::numeric_limits<int64_t>::max(),
|
|
std::numeric_limits<int32_t>::max()},
|
|
{std::numeric_limits<int64_t>::max() / 2 + 42,
|
|
std::numeric_limits<int32_t>::max()},
|
|
{std::numeric_limits<int32_t>::max(),
|
|
std::numeric_limits<int32_t>::max()},
|
|
{42, 42},
|
|
{0, 0},
|
|
{-42, -42},
|
|
{std::numeric_limits<int32_t>::min(),
|
|
std::numeric_limits<int32_t>::min()},
|
|
{std::numeric_limits<int64_t>::min() / 2 - 42,
|
|
std::numeric_limits<int32_t>::min()},
|
|
{std::numeric_limits<int64_t>::min(),
|
|
std::numeric_limits<int32_t>::min()},
|
|
};
|
|
for (const ValuePair& value_pair : kValuePairs) {
|
|
EXPECT_EQ(value_pair.to, saturate_cast<int32_t>(value_pair.from));
|
|
}
|
|
}
|
|
|
|
TEST(SaturateCastTest, LargerToSmallerUnsignedInteger) {
|
|
struct ValuePair {
|
|
uint64_t from;
|
|
uint32_t to;
|
|
};
|
|
constexpr ValuePair kValuePairs[] = {
|
|
{std::numeric_limits<uint64_t>::max(),
|
|
std::numeric_limits<uint32_t>::max()},
|
|
{std::numeric_limits<uint64_t>::max() / 2 + 42,
|
|
std::numeric_limits<uint32_t>::max()},
|
|
{std::numeric_limits<uint32_t>::max(),
|
|
std::numeric_limits<uint32_t>::max()},
|
|
{42, 42},
|
|
{0, 0},
|
|
};
|
|
for (const ValuePair& value_pair : kValuePairs) {
|
|
EXPECT_EQ(value_pair.to, saturate_cast<uint32_t>(value_pair.from));
|
|
}
|
|
}
|
|
|
|
TEST(SaturateCastTest, LargerSignedToSmallerUnsignedInteger) {
|
|
struct ValuePair {
|
|
int64_t from;
|
|
uint32_t to;
|
|
};
|
|
constexpr ValuePair kValuePairs[] = {
|
|
{std::numeric_limits<int64_t>::max(),
|
|
std::numeric_limits<uint32_t>::max()},
|
|
{std::numeric_limits<int64_t>::max() / 2 + 42,
|
|
std::numeric_limits<uint32_t>::max()},
|
|
{std::numeric_limits<uint32_t>::max(),
|
|
std::numeric_limits<uint32_t>::max()},
|
|
{42, 42},
|
|
{0, 0},
|
|
{-42, 0},
|
|
{std::numeric_limits<int64_t>::min() / 2 - 42, 0},
|
|
{std::numeric_limits<int64_t>::min(), 0},
|
|
};
|
|
for (const ValuePair& value_pair : kValuePairs) {
|
|
EXPECT_EQ(value_pair.to, saturate_cast<uint32_t>(value_pair.from));
|
|
}
|
|
}
|
|
|
|
TEST(SaturateCastTest, LargerUnsignedToSmallerSignedInteger) {
|
|
struct ValuePair {
|
|
uint64_t from;
|
|
int32_t to;
|
|
};
|
|
constexpr ValuePair kValuePairs[] = {
|
|
{std::numeric_limits<uint64_t>::max(),
|
|
std::numeric_limits<int32_t>::max()},
|
|
{std::numeric_limits<uint64_t>::max() / 2 + 42,
|
|
std::numeric_limits<int32_t>::max()},
|
|
{std::numeric_limits<int32_t>::max(),
|
|
std::numeric_limits<int32_t>::max()},
|
|
{42, 42},
|
|
{0, 0},
|
|
};
|
|
for (const ValuePair& value_pair : kValuePairs) {
|
|
EXPECT_EQ(value_pair.to, saturate_cast<int32_t>(value_pair.from));
|
|
}
|
|
}
|
|
|
|
TEST(SaturateCastTest, SignedToUnsigned32BitInteger) {
|
|
struct ValuePair {
|
|
int32_t from;
|
|
uint32_t to;
|
|
};
|
|
constexpr ValuePair kValuePairs[] = {
|
|
{std::numeric_limits<int32_t>::max(),
|
|
std::numeric_limits<int32_t>::max()},
|
|
{42, 42},
|
|
{0, 0},
|
|
{-42, 0},
|
|
{std::numeric_limits<int32_t>::min(), 0},
|
|
};
|
|
for (const ValuePair& value_pair : kValuePairs) {
|
|
EXPECT_EQ(value_pair.to, saturate_cast<uint32_t>(value_pair.from));
|
|
}
|
|
}
|
|
|
|
TEST(SaturateCastTest, UnsignedToSigned32BitInteger) {
|
|
struct ValuePair {
|
|
uint32_t from;
|
|
int32_t to;
|
|
};
|
|
constexpr ValuePair kValuePairs[] = {
|
|
{std::numeric_limits<uint32_t>::max(),
|
|
std::numeric_limits<int32_t>::max()},
|
|
{std::numeric_limits<uint32_t>::max() / 2 + 42,
|
|
std::numeric_limits<int32_t>::max()},
|
|
{std::numeric_limits<int32_t>::max(),
|
|
std::numeric_limits<int32_t>::max()},
|
|
{42, 42},
|
|
{0, 0},
|
|
};
|
|
for (const ValuePair& value_pair : kValuePairs) {
|
|
EXPECT_EQ(value_pair.to, saturate_cast<int32_t>(value_pair.from));
|
|
}
|
|
}
|
|
|
|
TEST(SaturateCastTest, SignedToUnsigned64BitInteger) {
|
|
struct ValuePair {
|
|
int64_t from;
|
|
uint64_t to;
|
|
};
|
|
constexpr ValuePair kValuePairs[] = {
|
|
{std::numeric_limits<int64_t>::max(),
|
|
std::numeric_limits<int64_t>::max()},
|
|
{42, 42},
|
|
{0, 0},
|
|
{-42, 0},
|
|
{std::numeric_limits<int64_t>::min(), 0},
|
|
};
|
|
for (const ValuePair& value_pair : kValuePairs) {
|
|
EXPECT_EQ(value_pair.to, saturate_cast<uint64_t>(value_pair.from));
|
|
}
|
|
}
|
|
|
|
TEST(SaturateCastTest, UnsignedToSigned64BitInteger) {
|
|
struct ValuePair {
|
|
uint64_t from;
|
|
int64_t to;
|
|
};
|
|
constexpr ValuePair kValuePairs[] = {
|
|
{std::numeric_limits<uint64_t>::max(),
|
|
std::numeric_limits<int64_t>::max()},
|
|
{std::numeric_limits<uint64_t>::max() / 2 + 42,
|
|
std::numeric_limits<int64_t>::max()},
|
|
{std::numeric_limits<int64_t>::max(),
|
|
std::numeric_limits<int64_t>::max()},
|
|
{42, 42},
|
|
{0, 0},
|
|
};
|
|
for (const ValuePair& value_pair : kValuePairs) {
|
|
EXPECT_EQ(value_pair.to, saturate_cast<int64_t>(value_pair.from));
|
|
}
|
|
}
|
|
|
|
TEST(SaturateCastTest, Float32ToSigned32) {
|
|
struct ValuePair {
|
|
float from;
|
|
int32_t to;
|
|
};
|
|
constexpr float kFloatMax = std::numeric_limits<float>::max();
|
|
// Note: kIntMax is one larger because float cannot represent the exact value.
|
|
constexpr float kIntMax =
|
|
static_cast<float>(std::numeric_limits<int32_t>::max());
|
|
constexpr float kIntMin = std::numeric_limits<int32_t>::min();
|
|
const ValuePair kValuePairs[] = {
|
|
{kFloatMax, std::numeric_limits<int32_t>::max()},
|
|
{std::nextafter(kIntMax, kFloatMax), std::numeric_limits<int32_t>::max()},
|
|
{kIntMax, std::numeric_limits<int32_t>::max()},
|
|
{std::nextafter(kIntMax, 0.f), 2147483520},
|
|
{42, 42},
|
|
{0, 0},
|
|
{-42, -42},
|
|
{std::nextafter(kIntMin, 0.f), -2147483520},
|
|
{kIntMin, std::numeric_limits<int32_t>::min()},
|
|
{std::nextafter(kIntMin, -kFloatMax),
|
|
std::numeric_limits<int32_t>::min()},
|
|
{-kFloatMax, std::numeric_limits<int32_t>::min()},
|
|
};
|
|
for (const ValuePair& value_pair : kValuePairs) {
|
|
EXPECT_EQ(value_pair.to, saturate_cast<int32_t>(value_pair.from));
|
|
}
|
|
}
|
|
|
|
TEST(SaturateCastTest, Float32ToSigned64) {
|
|
struct ValuePair {
|
|
float from;
|
|
int64_t to;
|
|
};
|
|
constexpr float kFloatMax = std::numeric_limits<float>::max();
|
|
// Note: kIntMax is one larger because float cannot represent the exact value.
|
|
constexpr float kIntMax =
|
|
static_cast<float>(std::numeric_limits<int64_t>::max());
|
|
constexpr float kIntMin = std::numeric_limits<int64_t>::min();
|
|
const ValuePair kValuePairs[] = {
|
|
{kFloatMax, std::numeric_limits<int64_t>::max()},
|
|
{std::nextafter(kIntMax, kFloatMax), std::numeric_limits<int64_t>::max()},
|
|
{kIntMax, std::numeric_limits<int64_t>::max()},
|
|
{std::nextafter(kIntMax, 0.f), INT64_C(9223371487098961920)},
|
|
{42, 42},
|
|
{0, 0},
|
|
{-42, -42},
|
|
{std::nextafter(kIntMin, 0.f), INT64_C(-9223371487098961920)},
|
|
{kIntMin, std::numeric_limits<int64_t>::min()},
|
|
{std::nextafter(kIntMin, -kFloatMax),
|
|
std::numeric_limits<int64_t>::min()},
|
|
{-kFloatMax, std::numeric_limits<int64_t>::min()},
|
|
};
|
|
for (const ValuePair& value_pair : kValuePairs) {
|
|
EXPECT_EQ(value_pair.to, saturate_cast<int64_t>(value_pair.from));
|
|
}
|
|
}
|
|
|
|
TEST(SaturateCastTest, Float64ToSigned32) {
|
|
struct ValuePair {
|
|
double from;
|
|
int32_t to;
|
|
};
|
|
constexpr double kDoubleMax = std::numeric_limits<double>::max();
|
|
constexpr double kIntMax = std::numeric_limits<int32_t>::max();
|
|
constexpr double kIntMin = std::numeric_limits<int32_t>::min();
|
|
const ValuePair kValuePairs[] = {
|
|
{kDoubleMax, std::numeric_limits<int32_t>::max()},
|
|
{std::nextafter(kIntMax, kDoubleMax),
|
|
std::numeric_limits<int32_t>::max()},
|
|
{kIntMax, std::numeric_limits<int32_t>::max()},
|
|
{std::nextafter(kIntMax, 0.0), std::numeric_limits<int32_t>::max() - 1},
|
|
{42, 42},
|
|
{0, 0},
|
|
{-42, -42},
|
|
{std::nextafter(kIntMin, 0.0), std::numeric_limits<int32_t>::min() + 1},
|
|
{kIntMin, std::numeric_limits<int32_t>::min()},
|
|
{std::nextafter(kIntMin, -kDoubleMax),
|
|
std::numeric_limits<int32_t>::min()},
|
|
{-kDoubleMax, std::numeric_limits<int32_t>::min()},
|
|
};
|
|
for (const ValuePair& value_pair : kValuePairs) {
|
|
EXPECT_EQ(value_pair.to, saturate_cast<int32_t>(value_pair.from));
|
|
}
|
|
}
|
|
|
|
TEST(SaturateCastTest, Float64ToSigned64) {
|
|
struct ValuePair {
|
|
double from;
|
|
int64_t to;
|
|
};
|
|
constexpr double kDoubleMax = std::numeric_limits<double>::max();
|
|
// Note: kIntMax is one larger because double cannot represent the exact
|
|
// value.
|
|
constexpr double kIntMax =
|
|
static_cast<double>(std::numeric_limits<int64_t>::max());
|
|
constexpr double kIntMin = std::numeric_limits<int64_t>::min();
|
|
const ValuePair kValuePairs[] = {
|
|
{kDoubleMax, std::numeric_limits<int64_t>::max()},
|
|
{std::nextafter(kIntMax, kDoubleMax),
|
|
std::numeric_limits<int64_t>::max()},
|
|
{kIntMax, std::numeric_limits<int64_t>::max()},
|
|
{std::nextafter(kIntMax, 0.0), INT64_C(9223372036854774784)},
|
|
{42, 42},
|
|
{0, 0},
|
|
{-42, -42},
|
|
{std::nextafter(kIntMin, 0.0), INT64_C(-9223372036854774784)},
|
|
{kIntMin, std::numeric_limits<int64_t>::min()},
|
|
{std::nextafter(kIntMin, -kDoubleMax),
|
|
std::numeric_limits<int64_t>::min()},
|
|
{-kDoubleMax, std::numeric_limits<int64_t>::min()},
|
|
};
|
|
for (const ValuePair& value_pair : kValuePairs) {
|
|
EXPECT_EQ(value_pair.to, saturate_cast<int64_t>(value_pair.from));
|
|
}
|
|
}
|
|
|
|
TEST(SaturateCastTest, Float32ToUnsigned64) {
|
|
struct ValuePair {
|
|
float from;
|
|
uint64_t to;
|
|
};
|
|
constexpr float kFloatMax = std::numeric_limits<float>::max();
|
|
// Note: kIntMax is one larger because float cannot represent the exact value.
|
|
constexpr float kIntMax =
|
|
static_cast<float>(std::numeric_limits<uint64_t>::max());
|
|
const ValuePair kValuePairs[] = {
|
|
{kFloatMax, std::numeric_limits<uint64_t>::max()},
|
|
{std::nextafter(kIntMax, kFloatMax),
|
|
std::numeric_limits<uint64_t>::max()},
|
|
{kIntMax, std::numeric_limits<uint64_t>::max()},
|
|
{std::nextafter(kIntMax, 0.f), UINT64_C(18446742974197923840)},
|
|
{42, 42},
|
|
{0, 0},
|
|
{-42, 0},
|
|
{-kFloatMax, 0},
|
|
};
|
|
for (const ValuePair& value_pair : kValuePairs) {
|
|
EXPECT_EQ(value_pair.to, saturate_cast<uint64_t>(value_pair.from));
|
|
}
|
|
}
|
|
|
|
TEST(SaturateCastTest, RoundingFloat32ToSigned64) {
|
|
struct ValuePair {
|
|
float from;
|
|
int64_t to;
|
|
};
|
|
constexpr float kFloatMax = std::numeric_limits<float>::max();
|
|
// Note: kIntMax is one larger because float cannot represent the exact value.
|
|
constexpr float kIntMax =
|
|
static_cast<float>(std::numeric_limits<int64_t>::max());
|
|
constexpr float kIntMin = std::numeric_limits<int64_t>::min();
|
|
const ValuePair kValuePairs[] = {
|
|
{kFloatMax, std::numeric_limits<int64_t>::max()},
|
|
{std::nextafter(kIntMax, kFloatMax), std::numeric_limits<int64_t>::max()},
|
|
{kIntMax, std::numeric_limits<int64_t>::max()},
|
|
{std::nextafter(kIntMax, 0.f), INT64_C(9223371487098961920)},
|
|
{41.9, 42},
|
|
{42, 42},
|
|
{42.6, 43},
|
|
{42.5, 43},
|
|
{42.4, 42},
|
|
{0.5, 1},
|
|
{0.1, 0},
|
|
{0, 0},
|
|
{-0.1, 0},
|
|
{-0.5, -1},
|
|
{-41.9, -42},
|
|
{-42, -42},
|
|
{-42.4, -42},
|
|
{-42.5, -43},
|
|
{-42.6, -43},
|
|
{std::nextafter(kIntMin, 0.f), INT64_C(-9223371487098961920)},
|
|
{kIntMin, std::numeric_limits<int64_t>::min()},
|
|
{std::nextafter(kIntMin, -kFloatMax),
|
|
std::numeric_limits<int64_t>::min()},
|
|
{-kFloatMax, std::numeric_limits<int64_t>::min()},
|
|
};
|
|
for (const ValuePair& value_pair : kValuePairs) {
|
|
EXPECT_EQ(value_pair.to, rounded_saturate_cast<int64_t>(value_pair.from));
|
|
}
|
|
}
|
|
|
|
} // namespace
|
|
} // namespace openscreen
|