blob: 62c8f3b0dcfa0582013117763650e017e87786ed [file] [log] [blame] [edit]
// 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