| // |
| // Copyright 2019 Google LLC |
| // |
| // 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 "algorithms/util.h" |
| |
| #include <limits> |
| #include <optional> |
| #include <vector> |
| |
| #include "base/testing/status_matchers.h" |
| #include "gmock/gmock.h" |
| #include "gtest/gtest.h" |
| #include "absl/status/status.h" |
| #include "algorithms/distributions.h" |
| #include "algorithms/numerical-mechanisms-testing.h" |
| |
| namespace differential_privacy { |
| namespace { |
| |
| using ::testing::HasSubstr; |
| using ::differential_privacy::base::testing::StatusIs; |
| |
| const char kSeedString[] = "ABCDEFGHIJKLMNOP"; |
| constexpr int64_t kStatsSize = 50000; |
| constexpr double kTolerance = 1e-5; |
| |
| TEST(EpsilonRiskValuesTest, DefaultEpsilon) { |
| EXPECT_EQ(DefaultEpsilon(), std::log(3)); |
| } |
| |
| TEST(NextPowerTest, PositivesPowers) { |
| EXPECT_NEAR(GetNextPowerOfTwo(3.0), 4.0, kTolerance); |
| EXPECT_NEAR(GetNextPowerOfTwo(5.0), 8.0, kTolerance); |
| EXPECT_NEAR(GetNextPowerOfTwo(7.9), 8.0, kTolerance); |
| } |
| |
| TEST(NextPowerTest, ExactPositivePowers) { |
| EXPECT_NEAR(GetNextPowerOfTwo(2.0), 2.0, kTolerance); |
| EXPECT_NEAR(GetNextPowerOfTwo(8.0), 8.0, kTolerance); |
| } |
| |
| TEST(NextPowerTest, One) { |
| EXPECT_NEAR(GetNextPowerOfTwo(1.0), 1.0, kTolerance); |
| } |
| |
| TEST(NextPowerTest, NegativePowers) { |
| EXPECT_NEAR(GetNextPowerOfTwo(0.4), 0.5, kTolerance); |
| EXPECT_NEAR(GetNextPowerOfTwo(0.2), 0.25, kTolerance); |
| } |
| |
| TEST(NextPowerTest, ExactNegativePowers) { |
| EXPECT_NEAR(GetNextPowerOfTwo(0.5), 0.5, kTolerance); |
| EXPECT_NEAR(GetNextPowerOfTwo(0.125), 0.125, kTolerance); |
| } |
| |
| TEST(InverseErrorTest, ProperResults) { |
| // true values are pre-calculated |
| EXPECT_NEAR(InverseErrorFunction(0.24), 0.216, 0.001); |
| EXPECT_NEAR(InverseErrorFunction(0.9999), 2.751, 0.001); |
| EXPECT_NEAR(InverseErrorFunction(0.0012), 0.001, 0.001); |
| EXPECT_NEAR(InverseErrorFunction(0.5), 0.476, 0.001); |
| EXPECT_NEAR(InverseErrorFunction(0.39), 0.360, 0.001); |
| EXPECT_NEAR(InverseErrorFunction(0.0067), 0.0059, 0.001); |
| |
| double max = 1; |
| double min = -1; |
| for (int i = 0; i < 1000; i++) { |
| double n = (max - min) * ((double)rand() / RAND_MAX) + min; |
| EXPECT_NEAR(std::erf(InverseErrorFunction(n)), n, 0.001); |
| } |
| } |
| |
| TEST(InverseErrorTest, EdgeCases) { |
| EXPECT_EQ(InverseErrorFunction(-1), |
| -1 * std::numeric_limits<double>::infinity()); |
| EXPECT_EQ(InverseErrorFunction(1), std::numeric_limits<double>::infinity()); |
| EXPECT_EQ(InverseErrorFunction(0), 0); |
| } |
| |
| // In RoundToNearestMultiple tests exact comparison of double is used, because |
| // for rounding to multiple of power of 2 RoundToNearestMultiple should provide |
| // exact value. |
| TEST(RoundDoubleTest, PositiveNoTies) { |
| EXPECT_EQ(RoundToNearestMultiple(4.9, 2.0), 4.0); |
| EXPECT_EQ(RoundToNearestMultiple(5.1, 2.0), 6.0); |
| } |
| |
| TEST(RoundDoubleTest, NegativesNoTies) { |
| EXPECT_EQ(RoundToNearestMultiple(-4.9, 2.0), -4.0); |
| EXPECT_EQ(RoundToNearestMultiple(-5.1, 2.0), -6.0); |
| } |
| |
| TEST(RoundDoubleTest, PositiveTies) { |
| EXPECT_EQ(RoundToNearestMultiple(5.0, 2.0), 6.0); |
| } |
| |
| TEST(RoundDoubleTest, NegativeTies) { |
| EXPECT_EQ(RoundToNearestMultiple(-5.0, 2.0), -4.0); |
| } |
| |
| TEST(RoundDoubleTest, NegativePowerOf2) { |
| EXPECT_EQ(RoundToNearestMultiple(0.2078795763, 0.25), 0.25); |
| EXPECT_EQ(RoundToNearestMultiple(0.1, 1.0 / (1 << 10)), 0.099609375); |
| EXPECT_EQ(RoundToNearestMultiple(0.3, 1.0 / (1 << 30)), |
| 322122547.0 / (1 << 30)); |
| } |
| |
| TEST(RoundInt64Test, PositiveNoTies) { |
| EXPECT_EQ(RoundToNearestMultiple(7, 3), 6); |
| EXPECT_EQ(RoundToNearestMultiple(8, 3), 9); |
| EXPECT_EQ(RoundToNearestMultiple(9, 4), 8); |
| EXPECT_EQ(RoundToNearestMultiple(11, 4), 12); |
| EXPECT_EQ(RoundToNearestMultiple(10, 5), 10); |
| EXPECT_EQ(RoundToNearestMultiple(11, 5), 10); |
| EXPECT_EQ(RoundToNearestMultiple(12, 5), 10); |
| EXPECT_EQ(RoundToNearestMultiple(13, 5), 15); |
| EXPECT_EQ(RoundToNearestMultiple(14, 5), 15); |
| EXPECT_EQ(RoundToNearestMultiple(15, 5), 15); |
| EXPECT_EQ(RoundToNearestMultiple(14, 7), 14); |
| EXPECT_EQ(RoundToNearestMultiple(15, 7), 14); |
| EXPECT_EQ(RoundToNearestMultiple(16, 7), 14); |
| EXPECT_EQ(RoundToNearestMultiple(17, 7), 14); |
| EXPECT_EQ(RoundToNearestMultiple(18, 7), 21); |
| EXPECT_EQ(RoundToNearestMultiple(19, 7), 21); |
| EXPECT_EQ(RoundToNearestMultiple(20, 7), 21); |
| EXPECT_EQ(RoundToNearestMultiple(21, 7), 21); |
| } |
| |
| TEST(RoundInt64Test, PositiveTies) { |
| EXPECT_EQ(RoundToNearestMultiple(5, 2), 6); |
| EXPECT_EQ(RoundToNearestMultiple(10, 4), 12); |
| EXPECT_EQ(RoundToNearestMultiple(9, 6), 12); |
| EXPECT_EQ(RoundToNearestMultiple(12, 8), 16); |
| EXPECT_EQ(RoundToNearestMultiple(15, 10), 20); |
| } |
| |
| TEST(RoundInt64Test, NegativeNoTies) { |
| EXPECT_EQ(RoundToNearestMultiple(-7, 3), -6); |
| EXPECT_EQ(RoundToNearestMultiple(-8, 3), -9); |
| EXPECT_EQ(RoundToNearestMultiple(-9, 4), -8); |
| EXPECT_EQ(RoundToNearestMultiple(-11, 4), -12); |
| } |
| |
| TEST(RoundInt64Test, NegativeTies) { |
| EXPECT_EQ(RoundToNearestMultiple(-5, 2), -4); |
| EXPECT_EQ(RoundToNearestMultiple(-10, 4), -8); |
| } |
| |
| TEST(RoundInt64Test, LargeValues) { |
| const int64_t k2Pow29 = 1 << 29; |
| const int64_t k2Pow30 = 1 << 30; |
| |
| EXPECT_EQ(RoundToNearestMultiple(k2Pow29, k2Pow30), k2Pow30); |
| // Expect 0 since ties are broken towards +inf |
| EXPECT_EQ(RoundToNearestMultiple(-k2Pow29, k2Pow30), 0); |
| |
| EXPECT_EQ(RoundToNearestMultiple(k2Pow30 - 5, k2Pow30), k2Pow30); |
| EXPECT_EQ(RoundToNearestMultiple(-k2Pow30 + 5, k2Pow30), -k2Pow30); |
| } |
| |
| TEST(QnormTest, InvalidProbability) { |
| EXPECT_EQ(Qnorm(-0.1).status().code(), absl::StatusCode::kInvalidArgument); |
| EXPECT_EQ(Qnorm(0).status().code(), absl::StatusCode::kInvalidArgument); |
| EXPECT_EQ(Qnorm(1).status().code(), absl::StatusCode::kInvalidArgument); |
| EXPECT_EQ(Qnorm(2).status().code(), absl::StatusCode::kInvalidArgument); |
| } |
| TEST(QnormTest, Accuracy) { |
| double theoretical_accuracy = 4.5 * std::pow(10, -4); |
| std::vector<double> p = {0.0000001, 0.00001, 0.001, 0.05, 0.15, 0.25, |
| 0.35, 0.45, 0.55, 0.65, 0.75, 0.85, |
| 0.95, 0.999, 0.99999, 0.9999999}; |
| std::vector<double> exact = { |
| -5.199337582187471, -4.264890793922602, -3.090232306167813, |
| -1.6448536269514729, -1.0364333894937896, -0.6744897501960817, |
| -0.38532046640756773, -0.12566134685507402, 0.12566134685507402, |
| 0.38532046640756773, 0.6744897501960817, 1.0364333894937896, |
| 1.6448536269514729, 3.090232306167813, 4.264890793922602, |
| 5.199337582187471}; |
| for (int i = 0; i < p.size(); ++i) { |
| EXPECT_LE(std::abs(exact[i] - Qnorm(p[i]).value()), theoretical_accuracy); |
| } |
| } |
| |
| TEST(ClampTest, DefaultTest) { |
| EXPECT_EQ(Clamp(1, 3, 2), 2); |
| EXPECT_EQ(Clamp(1.0, 3.0, 4.0), 3); |
| EXPECT_EQ(Clamp(1.0, 3.0, -2.0), 1); |
| } |
| |
| TEST(SafeOperationsTest, SafeAddInt) { |
| SafeOpResult<int64_t> safe_add_result; |
| |
| safe_add_result = SafeAdd<int64_t>(10, 20); |
| EXPECT_FALSE(safe_add_result.overflow); |
| EXPECT_EQ(safe_add_result.value, 30); |
| |
| safe_add_result = SafeAdd<int64_t>(std::numeric_limits<int64_t>::max(), |
| std::numeric_limits<int64_t>::lowest()); |
| EXPECT_FALSE(safe_add_result.overflow); |
| EXPECT_EQ(safe_add_result.value, -1); |
| |
| safe_add_result = SafeAdd<int64_t>(std::numeric_limits<int64_t>::max(), 1); |
| EXPECT_TRUE(safe_add_result.overflow); |
| EXPECT_EQ(safe_add_result.value, std::numeric_limits<int64_t>::max()); |
| |
| safe_add_result = |
| SafeAdd<int64_t>(std::numeric_limits<int64_t>::lowest(), -1); |
| EXPECT_TRUE(safe_add_result.overflow); |
| EXPECT_EQ(safe_add_result.value, std::numeric_limits<int64_t>::lowest()); |
| |
| safe_add_result = SafeAdd<int64_t>(std::numeric_limits<int64_t>::lowest(), 0); |
| EXPECT_FALSE(safe_add_result.overflow); |
| EXPECT_EQ(safe_add_result.value, std::numeric_limits<int64_t>::lowest()); |
| } |
| |
| TEST(SafeOperationsTest, SafeAddDouble) { |
| SafeOpResult<double> safe_add_result; |
| |
| safe_add_result = SafeAdd<double>(10, 20); |
| EXPECT_FALSE(safe_add_result.overflow); |
| EXPECT_EQ(safe_add_result.value, 30); |
| |
| safe_add_result = SafeAdd<double>(std::numeric_limits<double>::max(), |
| std::numeric_limits<double>::lowest()); |
| EXPECT_FALSE(safe_add_result.overflow); |
| EXPECT_DOUBLE_EQ(safe_add_result.value, 0); |
| |
| safe_add_result = SafeAdd<double>(std::numeric_limits<double>::max(), 1.0); |
| EXPECT_FALSE(safe_add_result.overflow); |
| EXPECT_DOUBLE_EQ(safe_add_result.value, |
| std::numeric_limits<double>::infinity()); |
| |
| safe_add_result = |
| SafeAdd<double>(std::numeric_limits<double>::lowest(), -1.0); |
| EXPECT_FALSE(safe_add_result.overflow); |
| EXPECT_DOUBLE_EQ(safe_add_result.value, |
| -std::numeric_limits<double>::infinity()); |
| |
| safe_add_result = SafeAdd<double>(std::numeric_limits<double>::lowest(), 0.0); |
| EXPECT_FALSE(safe_add_result.overflow); |
| EXPECT_DOUBLE_EQ(safe_add_result.value, |
| std::numeric_limits<double>::lowest()); |
| } |
| |
| TEST(SafeOperationsTest, SafeSubtractInt) { |
| SafeOpResult<int64_t> safe_subtract_int64_result; |
| |
| safe_subtract_int64_result = SafeSubtract<int64_t>(10, 20); |
| EXPECT_FALSE(safe_subtract_int64_result.overflow); |
| EXPECT_EQ(safe_subtract_int64_result.value, -10); |
| |
| safe_subtract_int64_result = |
| SafeSubtract<int64_t>(0, std::numeric_limits<int64_t>::lowest()); |
| EXPECT_TRUE(safe_subtract_int64_result.overflow); |
| EXPECT_EQ(safe_subtract_int64_result.value, |
| std::numeric_limits<int64_t>::max()); |
| |
| safe_subtract_int64_result = |
| SafeSubtract<int64_t>(1, std::numeric_limits<int64_t>::lowest()); |
| EXPECT_TRUE(safe_subtract_int64_result.overflow); |
| EXPECT_EQ(safe_subtract_int64_result.value, |
| std::numeric_limits<int64_t>::max()); |
| |
| safe_subtract_int64_result = |
| SafeSubtract<int64_t>(-1, std::numeric_limits<int64_t>::lowest()); |
| EXPECT_FALSE(safe_subtract_int64_result.overflow); |
| EXPECT_EQ(safe_subtract_int64_result.value, |
| std::numeric_limits<int64_t>::max()); |
| |
| safe_subtract_int64_result = |
| SafeSubtract<int64_t>(std::numeric_limits<int64_t>::lowest(), |
| std::numeric_limits<int64_t>::lowest()); |
| EXPECT_FALSE(safe_subtract_int64_result.overflow); |
| EXPECT_EQ(safe_subtract_int64_result.value, 0); |
| |
| SafeOpResult<uint64_t> safe_subtract_uint64_result = |
| SafeSubtract<uint64_t>(1, std::numeric_limits<uint64_t>::lowest()); |
| EXPECT_FALSE(safe_subtract_uint64_result.overflow); |
| EXPECT_EQ(safe_subtract_uint64_result.value, 1); |
| } |
| |
| TEST(SafeOperationsTest, SafeSubtractDouble) { |
| SafeOpResult<double> safe_subtract_result; |
| |
| safe_subtract_result = SafeSubtract<double>(10.0, 20.0); |
| EXPECT_FALSE(safe_subtract_result.overflow); |
| EXPECT_DOUBLE_EQ(safe_subtract_result.value, -10.0); |
| |
| safe_subtract_result = |
| SafeSubtract<double>(1.0, std::numeric_limits<double>::lowest()); |
| EXPECT_FALSE(safe_subtract_result.overflow); |
| EXPECT_DOUBLE_EQ(safe_subtract_result.value, |
| std::numeric_limits<double>::infinity()); |
| |
| safe_subtract_result = |
| SafeSubtract<double>(-1.0, std::numeric_limits<double>::lowest()); |
| EXPECT_FALSE(safe_subtract_result.overflow); |
| EXPECT_DOUBLE_EQ(safe_subtract_result.value, |
| std::numeric_limits<double>::infinity()); |
| |
| safe_subtract_result = |
| SafeSubtract<double>(std::numeric_limits<double>::lowest(), |
| std::numeric_limits<double>::lowest()); |
| EXPECT_FALSE(safe_subtract_result.overflow); |
| EXPECT_DOUBLE_EQ(safe_subtract_result.value, 0); |
| } |
| |
| TEST(SafeOperationsTest, SafeSquare) { |
| SafeOpResult<int64_t> safe_square_int64_result; |
| |
| safe_square_int64_result = SafeSquare<int64_t>(-9); |
| EXPECT_FALSE(safe_square_int64_result.overflow); |
| EXPECT_EQ(safe_square_int64_result.value, 81); |
| |
| safe_square_int64_result = |
| SafeSquare<int64_t>(std::numeric_limits<int64_t>::max() - 1); |
| EXPECT_TRUE(safe_square_int64_result.overflow); |
| EXPECT_EQ(safe_square_int64_result.value, 0); |
| |
| safe_square_int64_result = |
| SafeSquare<int64_t>(std::numeric_limits<int64_t>::lowest() + 1); |
| EXPECT_TRUE(safe_square_int64_result.overflow); |
| EXPECT_EQ(safe_square_int64_result.value, 0); |
| |
| safe_square_int64_result = |
| SafeSquare<int64_t>(std::numeric_limits<int64_t>::lowest()); |
| EXPECT_TRUE(safe_square_int64_result.overflow); |
| EXPECT_EQ(safe_square_int64_result.value, 0); |
| |
| SafeOpResult<uint64_t> safe_square_uint64_result = |
| SafeSquare<uint64_t>(std::numeric_limits<uint64_t>::lowest()); |
| EXPECT_FALSE(safe_square_uint64_result.overflow); |
| } |
| |
| TEST(StatisticsTest, VectorStatistics) { |
| std::vector<double> a = {1, 5, 7, 9, 13}; |
| EXPECT_EQ(Mean(a), 7); |
| EXPECT_EQ(Variance(a), 16); |
| EXPECT_EQ(StandardDev(a), 4); |
| EXPECT_EQ(OrderStatistic(.60, a), 8); |
| EXPECT_EQ(OrderStatistic(0, a), 1); |
| EXPECT_EQ(OrderStatistic(1, a), 13); |
| } |
| |
| TEST(StatisticTest, VectorStatistics) { |
| std::vector<double> a; |
| EXPECT_EQ(Mean(a), 0); |
| EXPECT_EQ(Variance(a), 0); |
| } |
| |
| TEST(VectorUtilTest, VectorFilter) { |
| std::vector<double> v = {1, 2, 2, 3}; |
| std::vector<bool> selection = {false, true, true, false}; |
| std::vector<double> expected = {2, 2}; |
| EXPECT_THAT(VectorFilter(v, selection), testing::ContainerEq(expected)); |
| } |
| |
| TEST(VectorUtilTest, VectorToString) { |
| std::vector<double> v = {1, 2, 2, 3}; |
| EXPECT_EQ(VectorToString(v), "[1, 2, 2, 3]"); |
| } |
| |
| TEST(SafeCastFromDoubleTest, Converts20ToIntegral) { |
| SafeOpResult<int64_t> cast_result = SafeCastFromDouble<int64_t>(20.0); |
| EXPECT_EQ(cast_result.value, 20); |
| EXPECT_FALSE(cast_result.overflow); |
| } |
| |
| TEST(SafeCastFromDoubleTest, ConvertsMaxValueToMaxIntegral) { |
| SafeOpResult<int64_t> cast_result = |
| SafeCastFromDouble<int64_t>(std::numeric_limits<int64_t>::max()); |
| EXPECT_EQ(cast_result.value, std::numeric_limits<int64_t>::max()); |
| EXPECT_FALSE(cast_result.overflow); |
| } |
| |
| TEST(SafeCastFromDoubleTest, ConvertsMinDoubleValuesToZero) { |
| SafeOpResult<int64_t> cast_result = |
| SafeCastFromDouble<int64_t>(std::numeric_limits<double>::min()); |
| EXPECT_EQ(cast_result.value, 0); |
| EXPECT_FALSE(cast_result.overflow); |
| |
| cast_result = |
| SafeCastFromDouble<int64_t>(-std::numeric_limits<double>::min()); |
| EXPECT_EQ(cast_result.value, 0); |
| EXPECT_FALSE(cast_result.overflow); |
| } |
| |
| TEST(SafeCastFromDoubleTest, ConvertsLowestValueToLowestIntegral) { |
| SafeOpResult<int64_t> cast_result = |
| SafeCastFromDouble<int64_t>(std::numeric_limits<int64_t>::lowest()); |
| EXPECT_EQ(cast_result.value, std::numeric_limits<int64_t>::lowest()); |
| EXPECT_FALSE(cast_result.overflow); |
| } |
| |
| TEST(SafeCastFromDoubleTest, ConvertsOverLimitValueToOverflowedIntegral) { |
| std::vector<double> overflow_values = { |
| 1, |
| 2, |
| 3, |
| 4, |
| 5, |
| 10, |
| 1234, |
| static_cast<double>(std::numeric_limits<int16_t>::max() - 2), |
| static_cast<double>(std::numeric_limits<int16_t>::max() - 1), |
| static_cast<double>(std::numeric_limits<int16_t>::max())}; |
| SafeOpResult<int16_t> cast_result; |
| for (double overflow : overflow_values) { |
| cast_result = SafeCastFromDouble<int16_t>( |
| static_cast<double>(std::numeric_limits<int16_t>::max()) + overflow); |
| EXPECT_EQ(cast_result.value, |
| std::numeric_limits<int16_t>::lowest() - 1 + overflow); |
| EXPECT_TRUE(cast_result.overflow); |
| } |
| } |
| |
| TEST(SafeCastFromDoubleTest, ConvertsUnderLimitValueToUnderflowedIntegral) { |
| std::vector<double> overflow_values = { |
| 1, |
| 2, |
| 3, |
| 4, |
| 5, |
| 10, |
| 1234, |
| static_cast<double>(std::numeric_limits<int16_t>::max() - 2), |
| static_cast<double>(std::numeric_limits<int16_t>::max() - 1), |
| static_cast<double>(std::numeric_limits<int16_t>::max())}; |
| SafeOpResult<int16_t> cast_result; |
| for (double overflow : overflow_values) { |
| cast_result = SafeCastFromDouble<int16_t>( |
| static_cast<double>(std::numeric_limits<int16_t>::lowest()) - overflow); |
| EXPECT_EQ(cast_result.value, |
| std::numeric_limits<int16_t>::max() + 1 - overflow); |
| EXPECT_TRUE(cast_result.overflow); |
| } |
| } |
| |
| TEST(SafeCastFromDoubleTest, ConvertsHighValueToOverflowedIntegral) { |
| SafeOpResult<int64_t> cast_result = SafeCastFromDouble<int64_t>(1.0e200); |
| EXPECT_LE(cast_result.value, std::numeric_limits<int64_t>::max()); |
| EXPECT_TRUE(cast_result.overflow); |
| } |
| |
| TEST(SafeCastFromDoubleTest, ConvertsLowValueToUnderflowedIntegral) { |
| SafeOpResult<int64_t> cast_result = SafeCastFromDouble<int64_t>(-1.0e200); |
| EXPECT_GE(cast_result.value, std::numeric_limits<int64_t>::lowest()); |
| EXPECT_TRUE(cast_result.overflow); |
| } |
| |
| TEST(SafeCastFromDoubleTest, ReturnsFalseOnNanForIntegrals) { |
| SafeOpResult<int64_t> cast_result = SafeCastFromDouble<int64_t>(NAN); |
| EXPECT_EQ(cast_result.value, std::numeric_limits<int64_t>::quiet_NaN()); |
| EXPECT_TRUE(cast_result.overflow); |
| } |
| |
| // Combine all tests for float outputs. Should be nothing unexpected here since |
| // this is just a cast from double to float. |
| TEST(SafeCastFromDoubleTest, ForFloat) { |
| SafeOpResult<float> cast_result; |
| |
| // Normal case. |
| cast_result = SafeCastFromDouble<float>(0.5); |
| EXPECT_EQ(cast_result.value, 0.5); |
| EXPECT_FALSE(cast_result.overflow); |
| |
| // NaN double should convert into NaN float. |
| cast_result = SafeCastFromDouble<float>(NAN); |
| EXPECT_TRUE(std::isnan(cast_result.value)); |
| EXPECT_FALSE(cast_result.overflow); |
| |
| // High double should convert into infinite float. |
| cast_result = SafeCastFromDouble<float>(1.0e200); |
| EXPECT_TRUE(std::isinf(cast_result.value)); |
| EXPECT_FALSE(cast_result.overflow); |
| } |
| |
| TEST(ValidateTest, IsSet) { |
| absl::optional<double> opt; |
| EXPECT_THAT(ValidateIsSet(opt, "Test value"), |
| StatusIs(absl::StatusCode::kInvalidArgument, |
| HasSubstr("Test value must be set."))); |
| |
| opt = std::numeric_limits<double>::quiet_NaN(); |
| EXPECT_THAT(ValidateIsSet(opt, "Test value"), |
| StatusIs(absl::StatusCode::kInvalidArgument, |
| HasSubstr("Test value must be a valid numeric value"))); |
| |
| std::vector<double> success_values = { |
| -std::numeric_limits<double>::infinity(), |
| std::numeric_limits<double>::lowest(), |
| -1, |
| 0, |
| std::numeric_limits<double>::min(), |
| 1, |
| std::numeric_limits<double>::max(), |
| std::numeric_limits<double>::infinity()}; |
| |
| for (double value : success_values) { |
| EXPECT_OK(ValidateIsSet(value, "Test value")); |
| } |
| } |
| |
| TEST(ValidateTest, IsPositive) { |
| std::vector<double> success_values = { |
| std::numeric_limits<double>::min(), 1, std::numeric_limits<double>::max(), |
| std::numeric_limits<double>::infinity()}; |
| std::vector<double> error_values = {-std::numeric_limits<double>::infinity(), |
| std::numeric_limits<double>::lowest(), |
| -10, -1, 0}; |
| |
| for (double value : success_values) { |
| EXPECT_OK(ValidateIsPositive(value, "Test value")); |
| } |
| |
| for (double value : error_values) { |
| EXPECT_THAT(ValidateIsPositive(value, "Test value"), |
| StatusIs(absl::StatusCode::kInvalidArgument, |
| HasSubstr("Test value must be positive"))); |
| } |
| } |
| |
| TEST(ValidateTest, IsNonNegative) { |
| std::vector<double> success_values = { |
| 0, std::numeric_limits<double>::min(), 1, |
| std::numeric_limits<double>::max(), |
| std::numeric_limits<double>::infinity()}; |
| std::vector<double> error_values = {-std::numeric_limits<double>::infinity(), |
| std::numeric_limits<double>::lowest(), |
| -10, -1}; |
| |
| for (double value : success_values) { |
| EXPECT_OK(ValidateIsNonNegative(value, "Test value")); |
| } |
| |
| for (double value : error_values) { |
| EXPECT_THAT(ValidateIsNonNegative(value, "Test value"), |
| StatusIs(absl::StatusCode::kInvalidArgument, |
| HasSubstr("Test value must be non-negative"))); |
| } |
| } |
| |
| TEST(ValidateTest, IsFinite) { |
| std::vector<double> success_values = {std::numeric_limits<double>::lowest(), |
| -1, |
| 0, |
| std::numeric_limits<double>::min(), |
| 1, |
| std::numeric_limits<double>::max()}; |
| |
| std::vector<double> error_values = {-std::numeric_limits<double>::infinity(), |
| std::numeric_limits<double>::infinity()}; |
| |
| for (double value : success_values) { |
| EXPECT_OK(ValidateIsFinite(value, "Test value")); |
| } |
| |
| for (double value : error_values) { |
| EXPECT_THAT(ValidateIsFinite(value, "Test value"), |
| StatusIs(absl::StatusCode::kInvalidArgument, |
| HasSubstr("Test value must be finite"))); |
| } |
| } |
| |
| TEST(ValidateTest, IsFiniteAndPositive) { |
| std::vector<double> success_values = {std::numeric_limits<double>::min(), 1, |
| std::numeric_limits<double>::max()}; |
| std::vector<double> error_values = {-std::numeric_limits<double>::infinity(), |
| std::numeric_limits<double>::lowest(), |
| -10, |
| -1, |
| 0, |
| std::numeric_limits<double>::infinity()}; |
| |
| for (double value : success_values) { |
| EXPECT_OK(ValidateIsFiniteAndPositive(value, "Test value")); |
| } |
| |
| for (double value : error_values) { |
| EXPECT_THAT(ValidateIsFiniteAndPositive(value, "Test value"), |
| StatusIs(absl::StatusCode::kInvalidArgument, |
| HasSubstr("Test value must be finite and positive"))); |
| } |
| } |
| |
| TEST(ValidateTest, IsFiniteAndNonNegative) { |
| std::vector<double> success_values = {0, std::numeric_limits<double>::min(), |
| 1, std::numeric_limits<double>::max()}; |
| std::vector<double> error_values = {-std::numeric_limits<double>::infinity(), |
| std::numeric_limits<double>::lowest(), |
| -10, -1, |
| std::numeric_limits<double>::infinity()}; |
| |
| for (double value : success_values) { |
| EXPECT_OK(ValidateIsFiniteAndNonNegative(value, "Test value")); |
| } |
| |
| for (double value : error_values) { |
| EXPECT_THAT( |
| ValidateIsFiniteAndNonNegative(value, "Test value"), |
| StatusIs(absl::StatusCode::kInvalidArgument, |
| HasSubstr("Test value must be finite and non-negative"))); |
| } |
| } |
| |
| TEST(ValidateTest, IsLesserThanOkStatus) { |
| struct LesserThanParams { |
| double value; |
| double upper_bound; |
| }; |
| |
| std::vector<LesserThanParams> success_params = { |
| {-std::numeric_limits<double>::infinity(), |
| std::numeric_limits<double>::lowest()}, |
| {-1, 1}, |
| {0, std::numeric_limits<double>::min()}, |
| {std::numeric_limits<double>::max(), |
| std::numeric_limits<double>::infinity()}, |
| }; |
| |
| for (LesserThanParams params : success_params) { |
| EXPECT_OK( |
| ValidateIsLesserThan(params.value, params.upper_bound, "Test value")); |
| } |
| } |
| |
| TEST(ValidateTest, IsLesserThanError) { |
| struct LesserThanParams { |
| double value; |
| double upper_bound; |
| }; |
| |
| std::vector<LesserThanParams> no_equal_error_params = { |
| {-std::numeric_limits<double>::infinity(), |
| -std::numeric_limits<double>::infinity()}, |
| {std::numeric_limits<double>::lowest(), |
| std::numeric_limits<double>::lowest()}, |
| {-1, -1}, |
| {std::numeric_limits<double>::min(), std::numeric_limits<double>::min()}, |
| {0, 0}, |
| {1, -1}, |
| {1, 1}, |
| {std::numeric_limits<double>::max(), std::numeric_limits<double>::max()}, |
| {std::numeric_limits<double>::infinity(), |
| std::numeric_limits<double>::infinity()}}; |
| |
| for (LesserThanParams params : no_equal_error_params) { |
| EXPECT_THAT( |
| ValidateIsLesserThan(params.value, params.upper_bound, "Test value"), |
| StatusIs(absl::StatusCode::kInvalidArgument, |
| HasSubstr("Test value must be lesser than"))); |
| } |
| } |
| |
| TEST(ValidateTest, IsLesserThanUnsetError) { |
| std::optional<double> test_unset; |
| |
| EXPECT_THAT(ValidateIsLesserThan(test_unset, 1, "Test value"), |
| StatusIs(absl::StatusCode::kInvalidArgument, |
| HasSubstr("Test value must be set"))); |
| } |
| |
| TEST(ValidateTest, IsLesserThanNaNError) { |
| EXPECT_THAT(ValidateIsLesserThan(std::numeric_limits<double>::quiet_NaN(), 1, |
| "Test value"), |
| StatusIs(absl::StatusCode::kInvalidArgument, |
| HasSubstr("Test value must be a valid numeric value"))); |
| } |
| |
| TEST(ValidateTest, IsLesserThanOrEqualToOkStatus) { |
| struct LesserThanParams { |
| double value; |
| double upper_bound; |
| }; |
| |
| std::vector<LesserThanParams> success_params = { |
| {-std::numeric_limits<double>::infinity(), |
| -std::numeric_limits<double>::infinity()}, |
| {std::numeric_limits<double>::lowest(), |
| std::numeric_limits<double>::lowest()}, |
| {-1, -1}, |
| {-1, 1}, |
| {0, 0}, |
| {std::numeric_limits<double>::min(), std::numeric_limits<double>::min()}, |
| { |
| 1, |
| 1, |
| }, |
| {std::numeric_limits<double>::max(), std::numeric_limits<double>::max()}, |
| {std::numeric_limits<double>::infinity(), |
| std::numeric_limits<double>::infinity()}}; |
| |
| for (LesserThanParams params : success_params) { |
| EXPECT_OK(ValidateIsLesserThanOrEqualTo(params.value, params.upper_bound, |
| "Test value")); |
| } |
| } |
| |
| TEST(ValidateTest, IsLesserThanOrEqualToError) { |
| struct LesserThanParams { |
| double value; |
| double upper_bound; |
| }; |
| |
| std::vector<LesserThanParams> or_equal_error_params = { |
| {std::numeric_limits<double>::lowest(), |
| -std::numeric_limits<double>::infinity()}, |
| {std::numeric_limits<double>::min(), 0}, |
| {1, -1}, |
| {std::numeric_limits<double>::infinity(), |
| std::numeric_limits<double>::max()}}; |
| |
| for (LesserThanParams params : or_equal_error_params) { |
| EXPECT_THAT( |
| ValidateIsLesserThanOrEqualTo(params.value, params.upper_bound, |
| "Test value"), |
| StatusIs(absl::StatusCode::kInvalidArgument, |
| HasSubstr("Test value must be lesser than or equal to"))); |
| } |
| } |
| |
| TEST(ValidateTest, IsLesserThanOrEqualToUnsetError) { |
| std::optional<double> test_unset; |
| |
| EXPECT_THAT(ValidateIsLesserThanOrEqualTo(test_unset, 1, "Test value"), |
| StatusIs(absl::StatusCode::kInvalidArgument, |
| HasSubstr("Test value must be set"))); |
| } |
| |
| TEST(ValidateTest, IsLesserThanOrEqualToNaNError) { |
| EXPECT_THAT(ValidateIsLesserThanOrEqualTo( |
| std::numeric_limits<double>::quiet_NaN(), 1, "Test value"), |
| StatusIs(absl::StatusCode::kInvalidArgument, |
| HasSubstr("Test value must be a valid numeric value"))); |
| } |
| |
| TEST(ValidateTest, IsGreaterThanOkStatus) { |
| struct GreaterThanParams { |
| double value; |
| double lower_bound; |
| }; |
| |
| std::vector<GreaterThanParams> success_params = { |
| {std::numeric_limits<double>::lowest(), |
| -std::numeric_limits<double>::infinity()}, |
| {std::numeric_limits<double>::min(), 0}, |
| {1, -1}, |
| {std::numeric_limits<double>::infinity(), |
| std::numeric_limits<double>::max()}, |
| }; |
| |
| for (GreaterThanParams params : success_params) { |
| EXPECT_OK( |
| ValidateIsGreaterThan(params.value, params.lower_bound, "Test value")); |
| } |
| } |
| |
| TEST(ValidateTest, IsGreaterThanError) { |
| struct GreaterThanParams { |
| double value; |
| double lower_bound; |
| }; |
| |
| std::vector<GreaterThanParams> no_equal_error_params = { |
| {-std::numeric_limits<double>::infinity(), |
| -std::numeric_limits<double>::infinity()}, |
| {std::numeric_limits<double>::lowest(), |
| std::numeric_limits<double>::lowest()}, |
| {-1, -1}, |
| {std::numeric_limits<double>::min(), std::numeric_limits<double>::min()}, |
| {0, 0}, |
| {-1, 1}, |
| {1, 1}, |
| {std::numeric_limits<double>::max(), std::numeric_limits<double>::max()}, |
| {std::numeric_limits<double>::infinity(), |
| std::numeric_limits<double>::infinity()}}; |
| |
| for (GreaterThanParams params : no_equal_error_params) { |
| EXPECT_THAT( |
| ValidateIsGreaterThan(params.value, params.lower_bound, "Test value"), |
| StatusIs(absl::StatusCode::kInvalidArgument, |
| HasSubstr("Test value must be greater than"))); |
| } |
| } |
| |
| TEST(ValidateTest, IsGreaterThanUnsetError) { |
| std::optional<double> test_unset; |
| |
| EXPECT_THAT(ValidateIsGreaterThan(test_unset, 1, "Test value"), |
| StatusIs(absl::StatusCode::kInvalidArgument, |
| HasSubstr("Test value must be set"))); |
| } |
| |
| TEST(ValidateTest, IsGreaterThanNaNError) { |
| EXPECT_THAT(ValidateIsGreaterThan(std::numeric_limits<double>::quiet_NaN(), 1, |
| "Test value"), |
| StatusIs(absl::StatusCode::kInvalidArgument, |
| HasSubstr("Test value must be a valid numeric value"))); |
| } |
| |
| TEST(ValidateTest, IsGreaterThanOrEqualToOkStatus) { |
| struct GreaterThanParams { |
| double value; |
| double lower_bound; |
| }; |
| |
| std::vector<GreaterThanParams> success_params = { |
| {-std::numeric_limits<double>::infinity(), |
| -std::numeric_limits<double>::infinity()}, |
| {std::numeric_limits<double>::lowest(), |
| std::numeric_limits<double>::lowest()}, |
| {-1, -1}, |
| {0, 0}, |
| {1, -1}, |
| {std::numeric_limits<double>::min(), std::numeric_limits<double>::min()}, |
| {1, 1}, |
| {std::numeric_limits<double>::max(), std::numeric_limits<double>::max()}, |
| {std::numeric_limits<double>::infinity(), |
| std::numeric_limits<double>::infinity()}}; |
| |
| for (GreaterThanParams params : success_params) { |
| EXPECT_OK(ValidateIsGreaterThanOrEqualTo(params.value, params.lower_bound, |
| "Test value")); |
| } |
| } |
| |
| TEST(ValidateTest, IsGreaterThanOrEqualToError) { |
| struct GreaterThanParams { |
| double value; |
| double lower_bound; |
| }; |
| |
| std::vector<GreaterThanParams> or_equal_error_params = { |
| {-std::numeric_limits<double>::infinity(), |
| std::numeric_limits<double>::lowest()}, |
| {0, std::numeric_limits<double>::min()}, |
| {-1, 1}, |
| {std::numeric_limits<double>::max(), |
| std::numeric_limits<double>::infinity()}}; |
| |
| for (GreaterThanParams params : or_equal_error_params) { |
| EXPECT_THAT( |
| ValidateIsGreaterThanOrEqualTo(params.value, params.lower_bound, |
| "Test value"), |
| StatusIs(absl::StatusCode::kInvalidArgument, |
| HasSubstr("Test value must be greater than or equal to"))); |
| } |
| } |
| |
| TEST(ValidateTest, IsGreaterThanOrEqualToUnsetError) { |
| std::optional<double> test_unset; |
| |
| EXPECT_THAT(ValidateIsGreaterThanOrEqualTo(test_unset, 1, "Test value"), |
| StatusIs(absl::StatusCode::kInvalidArgument, |
| HasSubstr("Test value must be set"))); |
| } |
| |
| TEST(ValidateTest, IsGreaterThanOrEqualToNaNError) { |
| EXPECT_THAT(ValidateIsGreaterThanOrEqualTo( |
| std::numeric_limits<double>::quiet_NaN(), 1, "Test value"), |
| StatusIs(absl::StatusCode::kInvalidArgument, |
| HasSubstr("Test value must be a valid numeric value"))); |
| } |
| |
| TEST(ValidateTest, IsInIntervalOkStatus) { |
| struct IntervalParams { |
| double value; |
| double lower_bound; |
| double upper_bound; |
| bool include_lower; |
| bool include_upper; |
| }; |
| |
| std::vector<IntervalParams> success_params = { |
| {std::numeric_limits<double>::lowest(), |
| std::numeric_limits<double>::lowest(), |
| std::numeric_limits<double>::lowest(), false, true}, |
| {std::numeric_limits<double>::lowest(), |
| std::numeric_limits<double>::lowest(), |
| std::numeric_limits<double>::lowest(), true, false}, |
| {std::numeric_limits<double>::lowest(), |
| std::numeric_limits<double>::lowest(), |
| std::numeric_limits<double>::lowest(), true, true}, |
| {0, -1, 1, false, false}, |
| {0, -1, 1, true, false}, |
| {0, -1, 1, false, true}, |
| {0, -1, 1, true, true}, |
| {0, 0, 0, false, true}, |
| {0, 0, 0, true, false}, |
| {0, 0, 0, true, true}, |
| {0.0, 0.0 - std::numeric_limits<double>::min(), |
| 0.0 + std::numeric_limits<double>::min(), false, false}, |
| {-1, -1, 1, true, false}, |
| {1, -1, 1, false, true}, |
| {1, 1, 1, false, true}, |
| {1, 1, 1, true, false}, |
| {1, 1, 1, true, true}, |
| {std::numeric_limits<double>::min(), std::numeric_limits<double>::min(), |
| std::numeric_limits<double>::min(), false, true}, |
| {std::numeric_limits<double>::min(), std::numeric_limits<double>::min(), |
| std::numeric_limits<double>::min(), true, false}, |
| {std::numeric_limits<double>::min(), std::numeric_limits<double>::min(), |
| std::numeric_limits<double>::min(), true, true}, |
| {std::numeric_limits<double>::max(), std::numeric_limits<double>::max(), |
| std::numeric_limits<double>::max(), false, true}, |
| {std::numeric_limits<double>::max(), std::numeric_limits<double>::max(), |
| std::numeric_limits<double>::max(), true, false}, |
| {std::numeric_limits<double>::max(), std::numeric_limits<double>::max(), |
| std::numeric_limits<double>::max(), true, true}, |
| }; |
| |
| for (IntervalParams params : success_params) { |
| EXPECT_OK(ValidateIsInInterval(params.value, params.lower_bound, |
| params.upper_bound, params.include_lower, |
| params.include_upper, "Test value")); |
| } |
| } |
| |
| TEST(ValidateTest, IsOutsideExclusiveInterval) { |
| struct IntervalParams { |
| double value; |
| double lower_bound; |
| double upper_bound; |
| bool include_lower; |
| bool include_upper; |
| }; |
| |
| std::vector<IntervalParams> exclusive_error_params = { |
| {std::numeric_limits<double>::lowest(), |
| std::numeric_limits<double>::lowest(), |
| std::numeric_limits<double>::lowest(), false, false}, |
| {-1, 0, 1, false, false}, |
| {-1, -1, -1, false, false}, |
| {0, 0, 0, false, false}, |
| {1, 1, 1, false, false}, |
| {std::numeric_limits<double>::min(), std::numeric_limits<double>::min(), |
| std::numeric_limits<double>::min(), false, false}, |
| {std::numeric_limits<double>::max(), std::numeric_limits<double>::max(), |
| std::numeric_limits<double>::max(), false, false}, |
| }; |
| |
| for (IntervalParams params : exclusive_error_params) { |
| EXPECT_THAT( |
| ValidateIsInInterval(params.value, params.lower_bound, |
| params.upper_bound, params.include_lower, |
| params.include_upper, "Test value"), |
| StatusIs(absl::StatusCode::kInvalidArgument, |
| HasSubstr("Test value must be in the exclusive interval ("))); |
| } |
| } |
| |
| TEST(ValidateTest, IsOutsideInclusiveInterval) { |
| struct IntervalParams { |
| double value; |
| double lower_bound; |
| double upper_bound; |
| bool include_lower; |
| bool include_upper; |
| }; |
| |
| std::vector<IntervalParams> inclusive_error_params = { |
| {-1, 0, 1, true, true}, |
| {0 - std::numeric_limits<double>::min(), 0, |
| std::numeric_limits<double>::min(), true, true}, |
| }; |
| |
| for (IntervalParams params : inclusive_error_params) { |
| EXPECT_THAT( |
| ValidateIsInInterval(params.value, params.lower_bound, |
| params.upper_bound, params.include_lower, |
| params.include_upper, "Test value"), |
| StatusIs(absl::StatusCode::kInvalidArgument, |
| HasSubstr("Test value must be in the inclusive interval ["))); |
| } |
| } |
| |
| TEST(ValidateTest, IsOutsideHalfClosedInterval) { |
| struct IntervalParams { |
| double value; |
| double lower_bound; |
| double upper_bound; |
| bool include_lower; |
| bool include_upper; |
| }; |
| |
| EXPECT_THAT(ValidateIsInInterval(-1, 0, 1, true, false, "Test value"), |
| StatusIs(absl::StatusCode::kInvalidArgument, |
| HasSubstr("Test value must be in the interval [0,1)"))); |
| |
| EXPECT_THAT(ValidateIsInInterval(-1, 0, 1, false, true, "Test value"), |
| StatusIs(absl::StatusCode::kInvalidArgument, |
| HasSubstr("Test value must be in the interval (0,1]"))); |
| |
| EXPECT_THAT(ValidateIsInInterval(-1, -1, 1, false, true, "Test value"), |
| StatusIs(absl::StatusCode::kInvalidArgument, |
| HasSubstr("Test value must be in the interval (-1,1]"))); |
| |
| EXPECT_THAT(ValidateIsInInterval(1, -1, 1, true, false, "Test value"), |
| StatusIs(absl::StatusCode::kInvalidArgument, |
| HasSubstr("Test value must be in the interval [-1,1)"))); |
| } |
| |
| // These tests document cases that result in known, incorrect behaviour |
| TEST(ValidateTest, IsInIntervalBadBehaviour) { |
| struct IntervalParams { |
| double value; |
| double lower_bound; |
| double upper_bound; |
| bool include_lower; |
| bool include_upper; |
| }; |
| |
| std::vector<IntervalParams> bad_exclusive_error_params = { |
| // These test parameters should result in an OK_STATUS since the value is |
| // within the bounds, but instead returns a kInvalidArgument status |
| // because of double (im)precision. |
| {-1.0, -1.0 - std::numeric_limits<double>::min(), |
| -1.0 + std::numeric_limits<double>::min(), false, false}, |
| {1.0, 1.0 - std::numeric_limits<double>::min(), |
| 1.0 + std::numeric_limits<double>::min(), false, false}, |
| }; |
| |
| for (IntervalParams params : bad_exclusive_error_params) { |
| EXPECT_THAT( |
| ValidateIsInInterval(params.value, params.lower_bound, |
| params.upper_bound, params.include_lower, |
| params.include_upper, "Test value"), |
| StatusIs(absl::StatusCode::kInvalidArgument, |
| HasSubstr("Test value must be in the exclusive interval ("))); |
| } |
| |
| std::vector<IntervalParams> bad_success_params = { |
| // These test parameters should result in an kInvalidArgument status since |
| // the value falls outside of the bounds, but instead returns an OK_STATUS |
| // because of double (im)precision. |
| {-1.0 - std::numeric_limits<double>::min(), -1.0, |
| -1.0 + std::numeric_limits<double>::min(), true, true}, |
| {1.0 - std::numeric_limits<double>::min(), 1.0, |
| 1.0 + std::numeric_limits<double>::min(), true, true}, |
| }; |
| |
| for (IntervalParams params : bad_success_params) { |
| EXPECT_OK(ValidateIsInInterval(params.value, params.lower_bound, |
| params.upper_bound, params.include_lower, |
| params.include_upper, "Test value")); |
| } |
| } |
| |
| TEST(ValidateTest, ValidateEpsilonFailsForNegativeAndNan) { |
| EXPECT_THAT(ValidateEpsilon(-1), StatusIs(absl::StatusCode::kInvalidArgument, |
| HasSubstr("positive"))); |
| EXPECT_THAT(ValidateEpsilon(0), StatusIs(absl::StatusCode::kInvalidArgument, |
| HasSubstr("positive"))); |
| EXPECT_THAT( |
| ValidateEpsilon(std::numeric_limits<double>::infinity()), |
| StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("finite"))); |
| EXPECT_THAT(ValidateEpsilon(std::numeric_limits<double>::quiet_NaN()), |
| StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("valid"))); |
| EXPECT_THAT(ValidateEpsilon(std::numeric_limits<double>::signaling_NaN()), |
| StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("valid"))); |
| } |
| |
| TEST(ValidateTest, ValidateEpsilonReturnsOkForPositive) { |
| EXPECT_THAT(ValidateEpsilon(0.1), StatusIs(absl::StatusCode::kOk)); |
| EXPECT_THAT(ValidateEpsilon(1.1), StatusIs(absl::StatusCode::kOk)); |
| EXPECT_THAT(ValidateEpsilon(std::log(3) / 2), |
| StatusIs(absl::StatusCode::kOk)); |
| EXPECT_THAT(ValidateEpsilon(std::log(3)), StatusIs(absl::StatusCode::kOk)); |
| EXPECT_THAT(ValidateEpsilon(100), StatusIs(absl::StatusCode::kOk)); |
| } |
| |
| TEST(ValidateTest, ValidateDeltaFailsForOutOfRangeValues) { |
| EXPECT_THAT(ValidateDelta(-1), StatusIs(absl::StatusCode::kInvalidArgument, |
| HasSubstr("inclusive interval"))); |
| EXPECT_THAT(ValidateDelta(1.1), StatusIs(absl::StatusCode::kInvalidArgument, |
| HasSubstr("inclusive interval"))); |
| EXPECT_THAT( |
| ValidateDelta(std::numeric_limits<double>::quiet_NaN()), |
| StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("valid numeric"))); |
| } |
| |
| TEST(ValidateTest, ValidateDeltaReturnsOkForInRange) { |
| EXPECT_THAT(ValidateDelta(0), StatusIs(absl::StatusCode::kOk)); |
| EXPECT_THAT(ValidateDelta(1e-50), StatusIs(absl::StatusCode::kOk)); |
| EXPECT_THAT(ValidateDelta(1e-8), StatusIs(absl::StatusCode::kOk)); |
| EXPECT_THAT(ValidateDelta(0.2), StatusIs(absl::StatusCode::kOk)); |
| EXPECT_THAT(ValidateDelta(1), StatusIs(absl::StatusCode::kOk)); |
| } |
| |
| TEST(ValidateTest, ValidateMaxPartitionsContributedFailsForNonPositive) { |
| EXPECT_THAT( |
| ValidateMaxPartitionsContributed(-1), |
| StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("positive"))); |
| EXPECT_THAT( |
| ValidateMaxPartitionsContributed(0), |
| StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("positive"))); |
| } |
| |
| TEST(ValidateTest, ValidateMaxPartitionsContributedReturnsOkForPositive) { |
| EXPECT_THAT(ValidateMaxPartitionsContributed(1), |
| StatusIs(absl::StatusCode::kOk)); |
| EXPECT_THAT(ValidateMaxPartitionsContributed(10), |
| StatusIs(absl::StatusCode::kOk)); |
| EXPECT_THAT(ValidateMaxPartitionsContributed(100), |
| StatusIs(absl::StatusCode::kOk)); |
| } |
| |
| TEST(ValidateTest, ValidateMaxContributions) { |
| EXPECT_THAT( |
| ValidateMaxContributions(-1), |
| StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("positive"))); |
| EXPECT_THAT( |
| ValidateMaxContributions(0), |
| StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("positive"))); |
| EXPECT_THAT(ValidateMaxPartitionsContributed(10), |
| StatusIs(absl::StatusCode::kOk)); |
| } |
| |
| TEST(ValidateTest, ValidateMaxContributionsPerPartitionFailsForNonPositive) { |
| EXPECT_THAT( |
| ValidateMaxContributionsPerPartition(-1), |
| StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("positive"))); |
| EXPECT_THAT( |
| ValidateMaxContributionsPerPartition(0), |
| StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("positive"))); |
| } |
| |
| TEST(ValidateTest, ValidateMaxContributionsPerPartitionReturnsOkForPositive) { |
| EXPECT_THAT(ValidateMaxContributionsPerPartition(1), |
| StatusIs(absl::StatusCode::kOk)); |
| EXPECT_THAT(ValidateMaxContributionsPerPartition(10), |
| StatusIs(absl::StatusCode::kOk)); |
| EXPECT_THAT(ValidateMaxContributionsPerPartition(100), |
| StatusIs(absl::StatusCode::kOk)); |
| } |
| |
| TEST(ValidateTest, ValidateBoundsChecksOrder) { |
| EXPECT_THAT(ValidateBounds<double>(1, 2), StatusIs(absl::StatusCode::kOk)); |
| EXPECT_THAT(ValidateBounds<double>(-2, 2), StatusIs(absl::StatusCode::kOk)); |
| EXPECT_THAT(ValidateBounds<double>(-2, -1), StatusIs(absl::StatusCode::kOk)); |
| |
| EXPECT_THAT(ValidateBounds<double>(2, 1), |
| StatusIs(absl::StatusCode::kInvalidArgument, |
| HasSubstr("bound cannot be greater"))); |
| EXPECT_THAT(ValidateBounds<double>(2, -1), |
| StatusIs(absl::StatusCode::kInvalidArgument, |
| HasSubstr("bound cannot be greater"))); |
| } |
| |
| TEST(ValidateTest, ValidateBoundsChecksBothSetOrUnset) { |
| EXPECT_THAT(ValidateBounds<double>(1, absl::nullopt), |
| StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("both"))); |
| EXPECT_THAT(ValidateBounds<double>(absl::nullopt, 1), |
| StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("both"))); |
| EXPECT_THAT(ValidateBounds<double>(absl::nullopt, absl::nullopt), |
| StatusIs(absl::StatusCode::kOk)); |
| } |
| |
| TEST(ValidateTest, ValidateBoundsFailsForNanBounds) { |
| EXPECT_THAT( |
| ValidateBounds<double>(1, std::numeric_limits<double>::infinity()), |
| StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("finite"))); |
| EXPECT_THAT( |
| ValidateBounds<double>(-std::numeric_limits<double>::infinity(), 1), |
| StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("finite"))); |
| } |
| |
| TEST(ValidateTest, ValidateTreeHeightForInvalidNumeric) { |
| EXPECT_THAT(ValidateTreeHeight(-1), |
| StatusIs(absl::StatusCode::kInvalidArgument, |
| HasSubstr("Height must be greater than or equal to 1"))); |
| EXPECT_THAT(ValidateTreeHeight(0), |
| StatusIs(absl::StatusCode::kInvalidArgument, |
| HasSubstr("Height must be greater than or equal to 1"))); |
| } |
| |
| TEST(ValidateTest, ValidateTreeHeightForEmpty) { |
| EXPECT_THAT(ValidateTreeHeight(absl::nullopt), |
| StatusIs(absl::StatusCode::kInvalidArgument, |
| HasSubstr("Tree Height must be set."))); |
| } |
| |
| TEST(ValidateTest, ValidateTreeHeightForOK) { |
| EXPECT_THAT(ValidateTreeHeight(1), StatusIs(absl::StatusCode::kOk)); |
| } |
| |
| TEST(ValidateTest, ValidateBranchingFactorForInvalidNumeric) { |
| EXPECT_THAT( |
| ValidateBranchingFactor(-1), |
| StatusIs( |
| absl::StatusCode::kInvalidArgument, |
| HasSubstr("Branching Factor must be greater than or equal to 2"))); |
| EXPECT_THAT( |
| ValidateBranchingFactor(0), |
| StatusIs( |
| absl::StatusCode::kInvalidArgument, |
| HasSubstr("Branching Factor must be greater than or equal to 2"))); |
| EXPECT_THAT( |
| ValidateBranchingFactor(1), |
| StatusIs( |
| absl::StatusCode::kInvalidArgument, |
| HasSubstr("Branching Factor must be greater than or equal to 2"))); |
| } |
| |
| TEST(ValidateTest, ValidateBranchingFactorForEmpty) { |
| EXPECT_THAT(ValidateBranchingFactor(absl::nullopt), |
| StatusIs(absl::StatusCode::kInvalidArgument, |
| HasSubstr("Branching Factor must be set"))); |
| } |
| |
| TEST(ValidateTest, ValidateBranchingFactorForOK) { |
| EXPECT_THAT(ValidateBranchingFactor(2), StatusIs(absl::StatusCode::kOk)); |
| } |
| |
| } // namespace |
| } // namespace differential_privacy |