| // 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 |
| // |
| // https://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 "runtime/cpp/emboss_arithmetic.h" |
| |
| #include "gtest/gtest.h" |
| |
| namespace emboss { |
| namespace support { |
| |
| // EXPECT_EQ uses operator==. For un-Known() Maybes, this follows the semantics |
| // for operator==(std::optional<T>, std::optional<T>), which returns true if |
| // neither argument has_value(). (It also matches Rust's Option and Haskell's |
| // Maybe.) |
| // |
| // Given the name "Known", it arguably should follow NaN != NaN semantics |
| // instead, but this is more useful for tests. |
| template <typename T> |
| constexpr inline bool operator==(const Maybe<T> &l, const Maybe<T> &r) { |
| return l.Known() == r.Known() && l.ValueOrDefault() == r.ValueOrDefault(); |
| } |
| |
| namespace test { |
| |
| using ::std::int32_t; |
| using ::std::int64_t; |
| using ::std::uint32_t; |
| using ::std::uint64_t; |
| |
| TEST(Sum, Sum) { |
| EXPECT_EQ( |
| Maybe</**/ ::std::int32_t>(0), |
| (Sum</**/ ::std::int32_t, ::std::int32_t, ::std::int32_t, ::std::int32_t>( |
| Maybe</**/ ::std::int32_t>(0), Maybe</**/ ::std::int32_t>(0)))); |
| EXPECT_EQ( |
| Maybe</**/ ::std::int32_t>(2147483647), |
| (Sum</**/ ::std::int32_t, ::std::int32_t, ::std::int32_t, ::std::int32_t>( |
| Maybe</**/ ::std::int32_t>(2147483646), |
| Maybe</**/ ::std::int32_t>(1)))); |
| EXPECT_EQ( |
| Maybe</**/ ::std::int32_t>(-2147483647 - 1), |
| (Sum</**/ ::std::int32_t, ::std::int32_t, ::std::int32_t, ::std::int32_t>( |
| Maybe</**/ ::std::int32_t>(-2147483647), |
| Maybe</**/ ::std::int32_t>(-1)))); |
| EXPECT_EQ(Maybe</**/ ::std::uint32_t>(2147483648U), |
| (Sum</**/ ::std::uint32_t, ::std::uint32_t, ::std::int32_t, |
| ::std::int32_t>(Maybe</**/ ::std::int32_t>(2147483647), |
| Maybe</**/ ::std::int32_t>(1)))); |
| EXPECT_EQ(Maybe</**/ ::std::int32_t>(2147483647), |
| (Sum</**/ ::std::int64_t, ::std::int32_t, ::std::uint32_t, |
| ::std::int32_t>(Maybe</**/ ::std::uint32_t>(2147483648U), |
| Maybe</**/ ::std::int32_t>(-1)))); |
| EXPECT_EQ(Maybe</**/ ::std::int32_t>(), |
| (Sum</**/ ::std::int64_t, ::std::int32_t, ::std::uint32_t, |
| ::std::int32_t>(Maybe</**/ ::std::uint32_t>(), |
| Maybe</**/ ::std::int32_t>(-1)))); |
| } |
| |
| TEST(Difference, Difference) { |
| EXPECT_EQ(Maybe</**/ ::std::int32_t>(0), |
| (Difference</**/ ::std::int32_t, ::std::int32_t, ::std::int32_t, |
| ::std::int32_t>(Maybe</**/ ::std::int32_t>(0), |
| Maybe</**/ ::std::int32_t>(0)))); |
| EXPECT_EQ(Maybe</**/ ::std::int32_t>(2147483647), |
| (Difference</**/ ::std::int32_t, ::std::int32_t, ::std::int32_t, |
| ::std::int32_t>(Maybe</**/ ::std::int32_t>(2147483646), |
| Maybe</**/ ::std::int32_t>(-1)))); |
| EXPECT_EQ(Maybe</**/ ::std::int32_t>(-2147483647 - 1), |
| (Difference</**/ ::std::int32_t, ::std::int32_t, ::std::int32_t, |
| ::std::int32_t>(Maybe</**/ ::std::int32_t>(-2147483647), |
| Maybe</**/ ::std::int32_t>(1)))); |
| EXPECT_EQ(Maybe</**/ ::std::uint32_t>(2147483648U), |
| (Difference</**/ ::std::uint32_t, ::std::uint32_t, ::std::int32_t, |
| ::std::int32_t>(Maybe</**/ ::std::int32_t>(2147483647), |
| Maybe</**/ ::std::int32_t>(-1)))); |
| EXPECT_EQ( |
| Maybe</**/ ::std::int32_t>(2147483647), |
| (Difference</**/ ::std::uint32_t, ::std::int32_t, ::std::uint32_t, |
| ::std::int32_t>(Maybe</**/ ::std::uint32_t>(2147483648U), |
| Maybe</**/ ::std::int32_t>(1)))); |
| EXPECT_EQ( |
| Maybe</**/ ::std::int32_t>(-2147483647 - 1), |
| (Difference</**/ ::std::int64_t, ::std::int32_t, ::std::int32_t, |
| ::std::uint32_t>(Maybe</**/ ::std::int32_t>(1), |
| Maybe</**/ ::std::uint32_t>(2147483649U)))); |
| EXPECT_EQ(Maybe</**/ ::std::int32_t>(), |
| (Difference</**/ ::std::int64_t, ::std::int32_t, ::std::int32_t, |
| ::std::uint32_t>(Maybe</**/ ::std::int32_t>(1), |
| Maybe</**/ ::std::uint32_t>()))); |
| } |
| |
| TEST(Product, Product) { |
| EXPECT_EQ(Maybe</**/ ::std::int32_t>(0), |
| (Product</**/ ::std::int32_t, ::std::int32_t, ::std::int32_t, |
| ::std::int32_t>(Maybe</**/ ::std::int32_t>(0), |
| Maybe</**/ ::std::int32_t>(0)))); |
| EXPECT_EQ(Maybe</**/ ::std::int32_t>(-2147483646), |
| (Product</**/ ::std::int32_t, ::std::int32_t, ::std::int32_t, |
| ::std::int32_t>(Maybe</**/ ::std::int32_t>(2147483646), |
| Maybe</**/ ::std::int32_t>(-1)))); |
| EXPECT_EQ( |
| Maybe</**/ ::std::int32_t>(-2147483647 - 1), |
| (Product</**/ ::std::int32_t, ::std::int32_t, ::std::int32_t, |
| ::std::int32_t>(Maybe</**/ ::std::int32_t>(-2147483647 - 1), |
| Maybe</**/ ::std::int32_t>(1)))); |
| EXPECT_EQ(Maybe</**/ ::std::uint32_t>(2147483648U), |
| (Product</**/ ::std::uint32_t, ::std::uint32_t, ::std::int32_t, |
| ::std::int32_t>(Maybe</**/ ::std::int32_t>(1073741824), |
| Maybe</**/ ::std::int32_t>(2)))); |
| EXPECT_EQ(Maybe</**/ ::std::uint32_t>(), |
| (Product</**/ ::std::uint32_t, ::std::uint32_t, ::std::int32_t, |
| ::std::int32_t>(Maybe</**/ ::std::int32_t>(), |
| Maybe</**/ ::std::int32_t>(2)))); |
| } |
| |
| TEST(Equal, Equal) { |
| EXPECT_EQ(Maybe<bool>(true), |
| (Equal</**/ ::std::int32_t, bool, ::std::int32_t, ::std::int32_t>( |
| Maybe</**/ ::std::int32_t>(0), Maybe</**/ ::std::int32_t>(0)))); |
| EXPECT_EQ(Maybe<bool>(false), |
| (Equal</**/ ::std::int32_t, bool, ::std::int32_t, ::std::int32_t>( |
| Maybe</**/ ::std::int32_t>(2147483646), |
| Maybe</**/ ::std::int32_t>(-1)))); |
| EXPECT_EQ(Maybe<bool>(true), |
| (Equal</**/ ::std::int32_t, bool, ::std::int32_t, ::std::uint32_t>( |
| Maybe</**/ ::std::int32_t>(2147483647), |
| Maybe</**/ ::std::uint32_t>(2147483647)))); |
| EXPECT_EQ(Maybe<bool>(false), |
| (Equal</**/ ::std::int64_t, bool, ::std::int32_t, ::std::uint32_t>( |
| Maybe</**/ ::std::int32_t>(-2147483648LL), |
| Maybe</**/ ::std::uint32_t>(2147483648U)))); |
| EXPECT_EQ(Maybe<bool>(), |
| (Equal</**/ ::std::int64_t, bool, ::std::int32_t, ::std::uint32_t>( |
| Maybe</**/ ::std::int32_t>(), |
| Maybe</**/ ::std::uint32_t>(2147483648U)))); |
| } |
| |
| TEST(NotEqual, NotEqual) { |
| EXPECT_EQ( |
| Maybe<bool>(false), |
| (NotEqual</**/ ::std::int32_t, bool, ::std::int32_t, ::std::int32_t>( |
| Maybe</**/ ::std::int32_t>(0), Maybe</**/ ::std::int32_t>(0)))); |
| EXPECT_EQ( |
| Maybe<bool>(true), |
| (NotEqual</**/ ::std::int32_t, bool, ::std::int32_t, ::std::int32_t>( |
| Maybe</**/ ::std::int32_t>(2147483646), |
| Maybe</**/ ::std::int32_t>(-1)))); |
| EXPECT_EQ( |
| Maybe<bool>(false), |
| (NotEqual</**/ ::std::int32_t, bool, ::std::int32_t, ::std::uint32_t>( |
| Maybe</**/ ::std::int32_t>(2147483647), |
| Maybe</**/ ::std::uint32_t>(2147483647)))); |
| EXPECT_EQ( |
| Maybe<bool>(true), |
| (NotEqual</**/ ::std::int64_t, bool, ::std::int32_t, ::std::uint32_t>( |
| Maybe</**/ ::std::int32_t>(-2147483648LL), |
| Maybe</**/ ::std::uint32_t>(2147483648U)))); |
| EXPECT_EQ( |
| Maybe<bool>(), |
| (NotEqual</**/ ::std::int64_t, bool, ::std::int32_t, ::std::uint32_t>( |
| Maybe</**/ ::std::int32_t>(-2147483648LL), |
| Maybe</**/ ::std::uint32_t>()))); |
| } |
| |
| TEST(LessThan, LessThan) { |
| EXPECT_EQ( |
| Maybe<bool>(false), |
| (LessThan</**/ ::std::int32_t, bool, ::std::int32_t, ::std::int32_t>( |
| Maybe</**/ ::std::int32_t>(0), Maybe</**/ ::std::int32_t>(0)))); |
| EXPECT_EQ( |
| Maybe<bool>(false), |
| (LessThan</**/ ::std::int32_t, bool, ::std::int32_t, ::std::int32_t>( |
| Maybe</**/ ::std::int32_t>(2147483646), |
| Maybe</**/ ::std::int32_t>(-1)))); |
| EXPECT_EQ( |
| Maybe<bool>(false), |
| (LessThan</**/ ::std::int32_t, bool, ::std::int32_t, ::std::uint32_t>( |
| Maybe</**/ ::std::int32_t>(2147483647), |
| Maybe</**/ ::std::uint32_t>(2147483647)))); |
| EXPECT_EQ( |
| Maybe<bool>(true), |
| (LessThan</**/ ::std::int64_t, bool, ::std::int32_t, ::std::uint32_t>( |
| Maybe</**/ ::std::int32_t>(-2147483648LL), |
| Maybe</**/ ::std::uint32_t>(2147483648U)))); |
| EXPECT_EQ( |
| Maybe<bool>(), |
| (LessThan</**/ ::std::int64_t, bool, ::std::int32_t, ::std::uint32_t>( |
| Maybe</**/ ::std::int32_t>(), |
| Maybe</**/ ::std::uint32_t>(2147483648U)))); |
| } |
| |
| TEST(LessThanOrEqual, LessThanOrEqual) { |
| EXPECT_EQ(Maybe<bool>(true), |
| (LessThanOrEqual</**/ ::std::int32_t, bool, ::std::int32_t, |
| ::std::int32_t>(Maybe</**/ ::std::int32_t>(0), |
| Maybe</**/ ::std::int32_t>(0)))); |
| EXPECT_EQ( |
| Maybe<bool>(false), |
| (LessThanOrEqual</**/ ::std::int32_t, bool, ::std::int32_t, |
| ::std::int32_t>(Maybe</**/ ::std::int32_t>(2147483646), |
| Maybe</**/ ::std::int32_t>(-1)))); |
| EXPECT_EQ(Maybe<bool>(true), |
| (LessThanOrEqual</**/ ::std::int32_t, bool, ::std::int32_t, |
| ::std::uint32_t>( |
| Maybe</**/ ::std::int32_t>(2147483647), |
| Maybe</**/ ::std::uint32_t>(2147483647)))); |
| EXPECT_EQ(Maybe<bool>(true), |
| (LessThanOrEqual</**/ ::std::int64_t, bool, ::std::int32_t, |
| ::std::uint32_t>( |
| Maybe</**/ ::std::int32_t>(-2147483648LL), |
| Maybe</**/ ::std::uint32_t>(2147483648U)))); |
| EXPECT_EQ(Maybe<bool>(), (LessThanOrEqual</**/ ::std::int64_t, bool, |
| ::std::int32_t, ::std::uint32_t>( |
| Maybe</**/ ::std::int32_t>(), |
| Maybe</**/ ::std::uint32_t>(2147483648U)))); |
| } |
| |
| TEST(GreaterThan, GreaterThan) { |
| EXPECT_EQ( |
| Maybe<bool>(false), |
| (GreaterThan</**/ ::std::int32_t, bool, ::std::int32_t, ::std::int32_t>( |
| Maybe</**/ ::std::int32_t>(0), Maybe</**/ ::std::int32_t>(0)))); |
| EXPECT_EQ( |
| Maybe<bool>(true), |
| (GreaterThan</**/ ::std::int32_t, bool, ::std::int32_t, ::std::int32_t>( |
| Maybe</**/ ::std::int32_t>(2147483646), |
| Maybe</**/ ::std::int32_t>(-1)))); |
| EXPECT_EQ( |
| Maybe<bool>(false), |
| (GreaterThan</**/ ::std::int32_t, bool, ::std::int32_t, ::std::uint32_t>( |
| Maybe</**/ ::std::int32_t>(2147483647), |
| Maybe</**/ ::std::uint32_t>(2147483647)))); |
| EXPECT_EQ( |
| Maybe<bool>(false), |
| (GreaterThan</**/ ::std::int64_t, bool, ::std::int32_t, ::std::uint32_t>( |
| Maybe</**/ ::std::int32_t>(-2147483648LL), |
| Maybe</**/ ::std::uint32_t>(2147483648U)))); |
| EXPECT_EQ( |
| Maybe<bool>(), |
| (GreaterThan</**/ ::std::int64_t, bool, ::std::int32_t, ::std::uint32_t>( |
| Maybe</**/ ::std::int32_t>(), |
| Maybe</**/ ::std::uint32_t>(2147483648U)))); |
| } |
| |
| TEST(GreaterThanOrEqual, GreaterThanOrEqual) { |
| EXPECT_EQ(Maybe<bool>(true), |
| (GreaterThanOrEqual</**/ ::std::int32_t, bool, ::std::int32_t, |
| ::std::int32_t>( |
| Maybe</**/ ::std::int32_t>(0), Maybe</**/ ::std::int32_t>(0)))); |
| EXPECT_EQ(Maybe<bool>(true), |
| (GreaterThanOrEqual</**/ ::std::int32_t, bool, ::std::int32_t, |
| ::std::int32_t>( |
| Maybe</**/ ::std::int32_t>(2147483646), |
| Maybe</**/ ::std::int32_t>(-1)))); |
| EXPECT_EQ(Maybe<bool>(true), |
| (GreaterThanOrEqual</**/ ::std::int32_t, bool, ::std::int32_t, |
| ::std::uint32_t>( |
| Maybe</**/ ::std::int32_t>(2147483647), |
| Maybe</**/ ::std::uint32_t>(2147483647)))); |
| EXPECT_EQ(Maybe<bool>(false), |
| (GreaterThanOrEqual</**/ ::std::int64_t, bool, ::std::int32_t, |
| ::std::uint32_t>( |
| Maybe</**/ ::std::int32_t>(-2147483648LL), |
| Maybe</**/ ::std::uint32_t>(2147483648U)))); |
| EXPECT_EQ(Maybe<bool>(), (GreaterThanOrEqual</**/ ::std::int64_t, bool, |
| ::std::int32_t, ::std::uint32_t>( |
| Maybe</**/ ::std::int32_t>(), |
| Maybe</**/ ::std::uint32_t>(2147483648U)))); |
| } |
| |
| TEST(And, And) { |
| EXPECT_EQ(Maybe<bool>(true), (And<bool, bool, bool, bool>( |
| Maybe<bool>(true), Maybe<bool>(true)))); |
| EXPECT_EQ(Maybe<bool>(), |
| (And<bool, bool, bool, bool>(Maybe<bool>(), Maybe<bool>(true)))); |
| EXPECT_EQ(Maybe<bool>(), |
| (And<bool, bool, bool, bool>(Maybe<bool>(), Maybe<bool>()))); |
| EXPECT_EQ(Maybe<bool>(), |
| (And<bool, bool, bool, bool>(Maybe<bool>(true), Maybe<bool>()))); |
| EXPECT_EQ(Maybe<bool>(false), (And<bool, bool, bool, bool>( |
| Maybe<bool>(false), Maybe<bool>(true)))); |
| EXPECT_EQ(Maybe<bool>(false), |
| (And<bool, bool, bool, bool>(Maybe<bool>(false), Maybe<bool>()))); |
| EXPECT_EQ(Maybe<bool>(false), (And<bool, bool, bool, bool>( |
| Maybe<bool>(false), Maybe<bool>(false)))); |
| EXPECT_EQ(Maybe<bool>(false), (And<bool, bool, bool, bool>( |
| Maybe<bool>(true), Maybe<bool>(false)))); |
| EXPECT_EQ(Maybe<bool>(false), |
| (And<bool, bool, bool, bool>(Maybe<bool>(), Maybe<bool>(false)))); |
| } |
| |
| TEST(Or, Or) { |
| EXPECT_EQ(Maybe<bool>(false), (Or<bool, bool, bool, bool>( |
| Maybe<bool>(false), Maybe<bool>(false)))); |
| EXPECT_EQ(Maybe<bool>(), |
| (Or<bool, bool, bool, bool>(Maybe<bool>(), Maybe<bool>(false)))); |
| EXPECT_EQ(Maybe<bool>(), |
| (Or<bool, bool, bool, bool>(Maybe<bool>(), Maybe<bool>()))); |
| EXPECT_EQ(Maybe<bool>(), |
| (Or<bool, bool, bool, bool>(Maybe<bool>(false), Maybe<bool>()))); |
| EXPECT_EQ(Maybe<bool>(true), (Or<bool, bool, bool, bool>(Maybe<bool>(false), |
| Maybe<bool>(true)))); |
| EXPECT_EQ(Maybe<bool>(true), |
| (Or<bool, bool, bool, bool>(Maybe<bool>(true), Maybe<bool>()))); |
| EXPECT_EQ(Maybe<bool>(true), |
| (Or<bool, bool, bool, bool>(Maybe<bool>(true), Maybe<bool>(true)))); |
| EXPECT_EQ(Maybe<bool>(true), (Or<bool, bool, bool, bool>( |
| Maybe<bool>(true), Maybe<bool>(false)))); |
| EXPECT_EQ(Maybe<bool>(true), |
| (Or<bool, bool, bool, bool>(Maybe<bool>(), Maybe<bool>(true)))); |
| } |
| |
| TEST(Choice, Choice) { |
| EXPECT_EQ(Maybe<int>(), (Choice<int, int, bool, int, int>( |
| Maybe<bool>(), Maybe<int>(1), Maybe<int>(2)))); |
| EXPECT_EQ(Maybe<int>(1), |
| (Choice<int, int, bool, int, int>(Maybe<bool>(true), Maybe<int>(1), |
| Maybe<int>(2)))); |
| EXPECT_EQ(Maybe<int>(2), |
| (Choice<int, int, bool, int, int>(Maybe<bool>(false), Maybe<int>(1), |
| Maybe<int>(2)))); |
| EXPECT_EQ(Maybe<int>(), (Choice<int, int, bool, int, int>( |
| Maybe<bool>(true), Maybe<int>(), Maybe<int>(2)))); |
| EXPECT_EQ(Maybe<int>(), |
| (Choice<int, int, bool, int, int>(Maybe<bool>(false), Maybe<int>(1), |
| Maybe<int>()))); |
| EXPECT_EQ( |
| Maybe</**/ ::std::int64_t>(2), |
| (Choice</**/ ::std::int64_t, ::std::int64_t, bool, ::std::int32_t, |
| ::std::int32_t>(Maybe<bool>(false), Maybe</**/ ::std::int32_t>(1), |
| Maybe</**/ ::std::int32_t>(2)))); |
| EXPECT_EQ(Maybe</**/ ::std::int64_t>(2), |
| (Choice</**/ ::std::int64_t, ::std::int64_t, bool, ::std::int32_t, |
| ::std::uint32_t>(Maybe<bool>(false), |
| Maybe</**/ ::std::int32_t>(-1), |
| Maybe</**/ ::std::uint32_t>(2)))); |
| EXPECT_EQ(Maybe</**/ ::std::int64_t>(-1), |
| (Choice</**/ ::std::int64_t, ::std::int64_t, bool, ::std::int32_t, |
| ::std::uint32_t>(Maybe<bool>(true), |
| Maybe</**/ ::std::int32_t>(-1), |
| Maybe</**/ ::std::uint32_t>(2)))); |
| EXPECT_EQ(Maybe<bool>(true), |
| (Choice<bool, bool, bool, bool, bool>( |
| Maybe<bool>(false), Maybe<bool>(false), Maybe<bool>(true)))); |
| } |
| |
| TEST(Maximum, Maximum) { |
| EXPECT_EQ(Maybe<int>(100), (Maximum<int, int, int>(Maybe<int>(100)))); |
| EXPECT_EQ(Maybe<int>(99), |
| (Maximum<int, int, int, int>(Maybe<int>(99), Maybe<int>(50)))); |
| EXPECT_EQ(Maybe<int>(98), |
| (Maximum<int, int, int, int>(Maybe<int>(50), Maybe<int>(98)))); |
| EXPECT_EQ(Maybe<int>(97), |
| (Maximum<int, int, int, int, int>(Maybe<int>(50), Maybe<int>(70), |
| Maybe<int>(97)))); |
| EXPECT_EQ(Maybe<int>(), (Maximum<int, int, int, int, int>( |
| Maybe<int>(50), Maybe<int>(), Maybe<int>(97)))); |
| EXPECT_EQ(Maybe<int>(-100), |
| (Maximum<int, int, int, int, int>( |
| Maybe<int>(-120), Maybe<int>(-150), Maybe<int>(-100)))); |
| EXPECT_EQ(Maybe<int>(), (Maximum<int, int, int>(Maybe<int>()))); |
| } |
| |
| } // namespace test |
| } // namespace support |
| } // namespace emboss |