| // Copyright 2020 The Chromium Authors | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include "util/simple_fraction.h" | |
| #include <cmath> | |
| #include <limits> | |
| #include "gtest/gtest.h" | |
| namespace openscreen { | |
| namespace { | |
| constexpr int kMin = std::numeric_limits<int>::min(); | |
| constexpr int kMax = std::numeric_limits<int>::max(); | |
| void ExpectFromStringEquals(const char* s, const SimpleFraction& expected) { | |
| const ErrorOr<SimpleFraction> f = SimpleFraction::FromString(std::string(s)); | |
| EXPECT_TRUE(f.is_value()) << "from string: '" << s << "'"; | |
| EXPECT_EQ(expected, f.value()); | |
| } | |
| void ExpectFromStringError(const char* s) { | |
| const auto f = SimpleFraction::FromString(std::string(s)); | |
| EXPECT_TRUE(f.is_error()) << "from string: '" << s << "'"; | |
| } | |
| } // namespace | |
| TEST(SimpleFractionTest, FromStringParsesCorrectFractions) { | |
| ExpectFromStringEquals("1/2", SimpleFraction{1, 2}); | |
| ExpectFromStringEquals("99/3", SimpleFraction{99, 3}); | |
| ExpectFromStringEquals("-1/2", SimpleFraction{-1, 2}); | |
| ExpectFromStringEquals("-13/-37", SimpleFraction{-13, -37}); | |
| ExpectFromStringEquals("1/0", SimpleFraction{1, 0}); | |
| ExpectFromStringEquals("1", SimpleFraction{1, 1}); | |
| ExpectFromStringEquals("0", SimpleFraction{0, 1}); | |
| ExpectFromStringEquals("-20", SimpleFraction{-20, 1}); | |
| ExpectFromStringEquals("100", SimpleFraction{100, 1}); | |
| ExpectFromStringEquals("1/", SimpleFraction{1, 1}); | |
| ExpectFromStringEquals("888/", SimpleFraction{888, 1}); | |
| } | |
| TEST(SimpleFractionTest, FromStringErrorsOnInvalid) { | |
| ExpectFromStringError(""); | |
| ExpectFromStringError("/"); | |
| ExpectFromStringError("/1"); | |
| ExpectFromStringError("1/2/3"); | |
| ExpectFromStringError("not a fraction at all"); | |
| } | |
| TEST(SimpleFractionTest, Equality) { | |
| EXPECT_EQ((SimpleFraction{1, 2}), (SimpleFraction{1, 2})); | |
| EXPECT_EQ((SimpleFraction{1, 0}), (SimpleFraction{1, 0})); | |
| EXPECT_NE((SimpleFraction{1, 2}), (SimpleFraction{1, 3})); | |
| // We currently don't do any reduction. | |
| EXPECT_NE((SimpleFraction{2, 4}), (SimpleFraction{1, 2})); | |
| EXPECT_NE((SimpleFraction{9, 10}), (SimpleFraction{-9, -10})); | |
| } | |
| TEST(SimpleFractionTest, Definition) { | |
| EXPECT_TRUE((SimpleFraction{kMin, 1}).is_defined()); | |
| EXPECT_TRUE((SimpleFraction{kMax, 1}).is_defined()); | |
| EXPECT_FALSE((SimpleFraction{kMin, 0}).is_defined()); | |
| EXPECT_FALSE((SimpleFraction{kMax, 0}).is_defined()); | |
| EXPECT_FALSE((SimpleFraction{0, 0}).is_defined()); | |
| EXPECT_FALSE((SimpleFraction{-0, -0}).is_defined()); | |
| } | |
| TEST(SimpleFractionTest, Positivity) { | |
| EXPECT_TRUE((SimpleFraction{1234, 20}).is_positive()); | |
| EXPECT_TRUE((SimpleFraction{kMax - 1, 20}).is_positive()); | |
| EXPECT_TRUE((SimpleFraction{0, kMax}).is_positive()); | |
| EXPECT_TRUE((SimpleFraction{kMax, 1}).is_positive()); | |
| // Since C++ doesn't have a truly negative zero, this is positive. | |
| EXPECT_TRUE((SimpleFraction{-0, 1}).is_positive()); | |
| EXPECT_FALSE((SimpleFraction{0, kMin}).is_positive()); | |
| EXPECT_FALSE((SimpleFraction{-0, -1}).is_positive()); | |
| EXPECT_FALSE((SimpleFraction{kMin + 1, 20}).is_positive()); | |
| EXPECT_FALSE((SimpleFraction{kMin, 1}).is_positive()); | |
| EXPECT_FALSE((SimpleFraction{kMin, 0}).is_positive()); | |
| EXPECT_FALSE((SimpleFraction{kMax, 0}).is_positive()); | |
| EXPECT_FALSE((SimpleFraction{0, 0}).is_positive()); | |
| EXPECT_FALSE((SimpleFraction{-0, -0}).is_positive()); | |
| } | |
| TEST(SimpleFractionTest, CastToDouble) { | |
| EXPECT_DOUBLE_EQ(0.0, static_cast<double>(SimpleFraction{0, 1})); | |
| EXPECT_DOUBLE_EQ(1.0, static_cast<double>(SimpleFraction{1, 1})); | |
| EXPECT_TRUE(std::isnan(static_cast<double>(SimpleFraction{1, 0}))); | |
| EXPECT_DOUBLE_EQ(1.0, static_cast<double>(SimpleFraction{kMax, kMax})); | |
| EXPECT_DOUBLE_EQ(1.0, static_cast<double>(SimpleFraction{kMin, kMin})); | |
| } | |
| } // namespace openscreen |