blob: e812d76a21cf75211532ba4d9c566a6189857aba [file] [log] [blame]
// Copyright 2022 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 "ink_stroke_modeler/types.h"
#include <cmath>
#include <limits>
#include <sstream>
#include <string>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "ink_stroke_modeler/internal/type_matchers.h"
namespace ink {
namespace stroke_model {
namespace {
using ::testing::Not;
TEST(TypesTest, Vec2Equality) {
EXPECT_EQ((Vec2{1, 2}), (Vec2{1, 2}));
EXPECT_EQ((Vec2{-.4, 17}), (Vec2{-.4, 17}));
EXPECT_NE((Vec2{1, 2}), (Vec2{1, 5}));
EXPECT_NE((Vec2{3, 2}), (Vec2{.7, 2}));
EXPECT_NE((Vec2{-4, .3}), (Vec2{.5, 12}));
}
TEST(TypesTest, Vec2EqMatcher) {
EXPECT_THAT((Vec2{1, 2}), Vec2Eq({1, 2}));
EXPECT_THAT((Vec2{3, 4}), Not(Vec2Eq({3, 5})));
EXPECT_THAT((Vec2{5, 6}), Not(Vec2Eq({4, 6})));
// Vec2Eq delegates to FloatEq, which uses a tolerance of 4 ULP.
constexpr float kEps = std::numeric_limits<float>::epsilon();
EXPECT_THAT((Vec2{1, 1}), Vec2Eq({1 + kEps, 1 - kEps}));
}
TEST(TypesTest, Vec2NearMatcher) {
EXPECT_THAT((Vec2{1, 2}), Vec2Near({1.05, 1.95}, .1));
EXPECT_THAT((Vec2{3, 4}), Not(Vec2Near({3, 5}, .5)));
EXPECT_THAT((Vec2{5, 6}), Not(Vec2Near({4, 6}, .5)));
}
TEST(TypesTest, Vec2Magnitude) {
EXPECT_FLOAT_EQ((Vec2{1, 1}).Magnitude(), std::sqrt(2));
EXPECT_FLOAT_EQ((Vec2{-3, 4}).Magnitude(), 5);
EXPECT_FLOAT_EQ((Vec2{0, 0}).Magnitude(), 0);
EXPECT_FLOAT_EQ((Vec2{0, 17}).Magnitude(), 17);
}
TEST(TypesTest, Vec2Addition) {
Vec2 a{3, 0};
Vec2 b{-1, .3};
Vec2 c{2.7, 4};
EXPECT_THAT(a + b, Vec2Eq({2, .3}));
EXPECT_THAT(a + c, Vec2Eq({5.7, 4}));
EXPECT_THAT(b + c, Vec2Eq({1.7, 4.3}));
}
TEST(TypesTest, Vec2Subtraction) {
Vec2 a{0, -2};
Vec2 b{.5, 19};
Vec2 c{1.1, -3.4};
EXPECT_THAT(a - b, Vec2Eq({-.5, -21}));
EXPECT_THAT(a - c, Vec2Eq({-1.1, 1.4}));
EXPECT_THAT(b - c, Vec2Eq({-.6, 22.4}));
}
TEST(TypesTest, Vec2ScalarMultiplication) {
Vec2 a{.7, -3};
Vec2 b{3, 5};
EXPECT_THAT(a * 2, Vec2Eq({1.4, -6}));
EXPECT_THAT(.1 * a, Vec2Eq({.07, -.3}));
EXPECT_THAT(b * -.3, Vec2Eq({-.9, -1.5}));
EXPECT_THAT(4 * b, Vec2({12, 20}));
}
TEST(TypesTest, Vec2ScalarDivision) {
Vec2 a{7, .9};
Vec2 b{-4.5, -2};
EXPECT_THAT(a / 2, Vec2Eq({3.5, .45}));
EXPECT_THAT(a / -.1, Vec2Eq({-70, -9}));
EXPECT_THAT(b / 5, Vec2Eq({-.9, -.4}));
EXPECT_THAT(b / .2, Vec2Eq({-22.5, -10}));
}
TEST(TypesTest, Vec2AddAssign) {
Vec2 a{1, 2};
a += {.x = 3, .y = -1};
EXPECT_THAT(a, Vec2Eq({4, 1}));
a += {.x = -.5, .y = 2};
EXPECT_THAT(a, Vec2Eq({3.5, 3}));
}
TEST(TypesTest, Vec2SubractAssign) {
Vec2 a{1, 2};
a -= {.x = 3, .y = -1};
EXPECT_THAT(a, Vec2Eq({-2, 3}));
a -= {.x = -.5, .y = 2};
EXPECT_THAT(a, Vec2Eq({-1.5, 1}));
}
TEST(TypesTest, Vec2ScalarMultiplyAssign) {
Vec2 a{1, 2};
a *= 2;
EXPECT_THAT(a, Vec2Eq({2, 4}));
a *= -.4;
EXPECT_THAT(a, Vec2Eq({-.8, -1.6}));
}
TEST(TypesTest, Vec2ScalarDivideAssign) {
Vec2 a{1, 2};
a /= 2;
EXPECT_THAT(a, Vec2Eq({.5, 1}));
a /= -.4;
EXPECT_THAT(a, Vec2Eq({-1.25, -2.5}));
}
TEST(TypesTest, Vec2Stream) {
std::stringstream s;
s << Vec2{3.5, -2.7};
EXPECT_EQ(s.str(), "(3.5, -2.7)");
}
TEST(TypesTest, DurationArithmetic) {
EXPECT_EQ(Duration(1) + Duration(2), Duration(3));
EXPECT_EQ(Duration(6) - Duration(1), Duration(5));
EXPECT_EQ(Duration(3) * 2, Duration(6));
EXPECT_EQ(.5 * Duration(7), Duration(3.5));
EXPECT_EQ(Duration(12) / 4, Duration(3));
}
TEST(TypesTest, DurationArithmeticAssignment) {
Duration d{5};
d += Duration(2);
EXPECT_EQ(d, Duration(7));
d -= Duration(3);
EXPECT_EQ(d, Duration(4));
d *= 5;
EXPECT_EQ(d, Duration(20));
d /= 2;
EXPECT_EQ(d, Duration(10));
}
TEST(TypesTest, DurationComparison) {
EXPECT_EQ(Duration(0), Duration(0));
EXPECT_NE(Duration(0), Duration(1));
EXPECT_LT(Duration(1), Duration(2));
EXPECT_LE(Duration(4), Duration(5));
EXPECT_LE(Duration(2), Duration(2));
EXPECT_GT(Duration(10), Duration(9));
EXPECT_GE(Duration(7), Duration(5));
EXPECT_GE(Duration(5), Duration(5));
}
TEST(TypesTest, TimeArithmetic) {
EXPECT_EQ(Time(5) + Duration(1), Time(6));
EXPECT_EQ(Duration(7) + Time(12), Time(19));
EXPECT_EQ(Time(23) - Duration(5), Time(18));
EXPECT_EQ(Time(35) - Time(7), Duration(28));
}
TEST(TypesTest, TimeArithmeticAssignment) {
Time t{20};
t += Duration(10);
EXPECT_EQ(t, Time(30));
t -= Duration(24);
EXPECT_EQ(t, Time(6));
}
TEST(TypesTest, TimeComparison) {
EXPECT_EQ(Time(0), Time(0));
EXPECT_NE(Time(0), Time(1));
EXPECT_LT(Time(1), Time(2));
EXPECT_LE(Time(4), Time(5));
EXPECT_LE(Time(2), Time(2));
EXPECT_GT(Time(10), Time(9));
EXPECT_GE(Time(7), Time(5));
EXPECT_GE(Time(5), Time(5));
}
TEST(TypesTest, InputEquality) {
const Input kBaseline{};
EXPECT_EQ(kBaseline, Input());
EXPECT_NE(kBaseline, Input{.event_type = Input::EventType::kMove});
EXPECT_NE(kBaseline, (Input{.position = {1, -1}}));
EXPECT_NE(kBaseline, Input{.time = Time(1)});
EXPECT_NE(kBaseline, Input{.pressure = .5});
EXPECT_NE(kBaseline, Input{.tilt = .2});
EXPECT_NE(kBaseline, Input{.orientation = .7});
}
} // namespace
} // namespace stroke_model
} // namespace ink