diff options
Diffstat (limited to 'gfx/tests/gtest/TestRect.cpp')
-rw-r--r-- | gfx/tests/gtest/TestRect.cpp | 450 |
1 files changed, 450 insertions, 0 deletions
diff --git a/gfx/tests/gtest/TestRect.cpp b/gfx/tests/gtest/TestRect.cpp new file mode 100644 index 000000000..056469507 --- /dev/null +++ b/gfx/tests/gtest/TestRect.cpp @@ -0,0 +1,450 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include <limits> + +#include "gtest/gtest.h" + +#include "nsRect.h" +#include "gfxRect.h" +#ifdef XP_WIN +#include <windows.h> +#endif + +template <class RectType> +static bool +TestConstructors() +{ + // Create a rectangle + RectType rect1(10, 20, 30, 40); + + // Make sure the rectangle was properly initialized + EXPECT_TRUE(rect1.x == 10 && rect1.y == 20 && + rect1.width == 30 && rect1.height == 40) << + "[1] Make sure the rectangle was properly initialized with constructor"; + + // Create a second rect using the copy constructor + RectType rect2(rect1); + + // Make sure the rectangle was properly initialized + EXPECT_TRUE(rect2.x == rect1.x && rect2.y == rect2.y && + rect2.width == rect2.width && rect2.height == rect2.height) << + "[2] Make sure the rectangle was properly initialized with copy constructor"; + + + EXPECT_TRUE(!rect1.IsEmpty() && rect1.IsFinite() && + !rect2.IsEmpty() && rect2.IsFinite()) << + "[3] These rectangles are not empty and are finite"; + + return true; +} + +template <class RectType> +static bool +TestEqualityOperator() +{ + RectType rect1(10, 20, 30, 40); + RectType rect2(rect1); + + // Test the equality operator + EXPECT_TRUE(rect1 == rect2) << + "[1] Test the equality operator"; + + EXPECT_FALSE(!rect1.IsEqualInterior(rect2)) << + "[2] Test the inequality operator"; + + // Make sure that two empty rects are equal + rect1.SetEmpty(); + rect2.SetEmpty(); + EXPECT_TRUE(rect1 == rect2) << + "[3] Make sure that two empty rects are equal"; + + return true; +} + +template <class RectType> +static bool +TestContainment() +{ + RectType rect1(10, 10, 50, 50); + + // Test the point containment methods + // + + // Basic test of a point in the middle of the rect + EXPECT_FALSE(!rect1.Contains(rect1.x + rect1.width/2, rect1.y + rect1.height/2)) << + "[1] Basic test of a point in the middle of the rect"; + + // Test against a point at the left/top edges + EXPECT_FALSE(!rect1.Contains(rect1.x, rect1.y)) << + "[2] Test against a point at the left/top edges"; + + // Test against a point at the right/bottom extents + EXPECT_FALSE(rect1.Contains(rect1.XMost(), rect1.YMost())) << + "[3] Test against a point at the right/bottom extents"; + + // Test the rect containment methods + // + RectType rect2(rect1); + + // Test against a rect that's the same as rect1 + EXPECT_FALSE(!rect1.Contains(rect2)) << + "[4] Test against a rect that's the same as rect1"; + + // Test against a rect whose left edge (only) is outside of rect1 + rect2.x--; + EXPECT_FALSE(rect1.Contains(rect2)) << + "[5] Test against a rect whose left edge (only) is outside of rect1"; + rect2.x++; + + // Test against a rect whose top edge (only) is outside of rect1 + rect2.y--; + EXPECT_FALSE(rect1.Contains(rect2)) << + "[6] Test against a rect whose top edge (only) is outside of rect1"; + rect2.y++; + + // Test against a rect whose right edge (only) is outside of rect1 + rect2.x++; + EXPECT_FALSE(rect1.Contains(rect2)) << + "[7] Test against a rect whose right edge (only) is outside of rect1"; + rect2.x--; + + // Test against a rect whose bottom edge (only) is outside of rect1 + rect2.y++; + EXPECT_FALSE(rect1.Contains(rect2)) << + "[8] Test against a rect whose bottom edge (only) is outside of rect1"; + rect2.y--; + + return true; +} + +// Test the method that returns a boolean result but doesn't return a +// a rectangle +template <class RectType> +static bool +TestIntersects() +{ + RectType rect1(10, 10, 50, 50); + RectType rect2(rect1); + + // Test against a rect that's the same as rect1 + EXPECT_FALSE(!rect1.Intersects(rect2)) << + "[1] Test against a rect that's the same as rect1"; + + // Test against a rect that's enclosed by rect1 + rect2.Inflate(-1, -1); + EXPECT_FALSE(!rect1.Contains(rect2) || !rect1.Intersects(rect2)) << + "[2] Test against a rect that's enclosed by rect1"; + rect2.Inflate(1, 1); + + // Make sure inflate and deflate worked correctly + EXPECT_TRUE(rect1.IsEqualInterior(rect2)) << + "[3] Make sure inflate and deflate worked correctly"; + + // Test against a rect that overlaps the left edge of rect1 + rect2.x--; + EXPECT_FALSE(!rect1.Intersects(rect2)) << + "[4] Test against a rect that overlaps the left edge of rect1"; + rect2.x++; + + // Test against a rect that's outside of rect1 on the left + rect2.x -= rect2.width; + EXPECT_FALSE(rect1.Intersects(rect2)) << + "[5] Test against a rect that's outside of rect1 on the left"; + rect2.x += rect2.width; + + // Test against a rect that overlaps the top edge of rect1 + rect2.y--; + EXPECT_FALSE(!rect1.Intersects(rect2)) << + "[6] Test against a rect that overlaps the top edge of rect1"; + rect2.y++; + + // Test against a rect that's outside of rect1 on the top + rect2.y -= rect2.height; + EXPECT_FALSE(rect1.Intersects(rect2)) << + "[7] Test against a rect that's outside of rect1 on the top"; + rect2.y += rect2.height; + + // Test against a rect that overlaps the right edge of rect1 + rect2.x++; + EXPECT_FALSE(!rect1.Intersects(rect2)) << + "[8] Test against a rect that overlaps the right edge of rect1"; + rect2.x--; + + // Test against a rect that's outside of rect1 on the right + rect2.x += rect2.width; + EXPECT_FALSE(rect1.Intersects(rect2)) << + "[9] Test against a rect that's outside of rect1 on the right"; + rect2.x -= rect2.width; + + // Test against a rect that overlaps the bottom edge of rect1 + rect2.y++; + EXPECT_FALSE(!rect1.Intersects(rect2)) << + "[10] Test against a rect that overlaps the bottom edge of rect1"; + rect2.y--; + + // Test against a rect that's outside of rect1 on the bottom + rect2.y += rect2.height; + EXPECT_FALSE(rect1.Intersects(rect2)) << + "[11] Test against a rect that's outside of rect1 on the bottom"; + rect2.y -= rect2.height; + + return true; +} + +// Test the method that returns a boolean result and an intersection rect +template <class RectType> +static bool +TestIntersection() +{ + RectType rect1(10, 10, 50, 50); + RectType rect2(rect1); + RectType dest; + + // Test against a rect that's the same as rect1 + EXPECT_FALSE(!dest.IntersectRect(rect1, rect2) || !(dest.IsEqualInterior(rect1))) << + "[1] Test against a rect that's the same as rect1"; + + // Test against a rect that's enclosed by rect1 + rect2.Inflate(-1, -1); + EXPECT_FALSE(!dest.IntersectRect(rect1, rect2) || !(dest.IsEqualInterior(rect2))) << + "[2] Test against a rect that's enclosed by rect1"; + rect2.Inflate(1, 1); + + // Test against a rect that overlaps the left edge of rect1 + rect2.x--; + EXPECT_FALSE(!dest.IntersectRect(rect1, rect2) || + !(dest.IsEqualInterior(RectType(rect1.x, rect1.y, rect1.width - 1, rect1.height)))) << + "[3] Test against a rect that overlaps the left edge of rect1"; + rect2.x++; + + // Test against a rect that's outside of rect1 on the left + rect2.x -= rect2.width; + EXPECT_FALSE(dest.IntersectRect(rect1, rect2)) << + "[4] Test against a rect that's outside of rect1 on the left"; + // Make sure an empty rect is returned + EXPECT_FALSE(!dest.IsEmpty()) << + "[4] Make sure an empty rect is returned"; + EXPECT_TRUE(dest.IsFinite()) << "[4b] Should be finite"; + rect2.x += rect2.width; + + // Test against a rect that overlaps the top edge of rect1 + rect2.y--; + EXPECT_FALSE(!dest.IntersectRect(rect1, rect2) || + !(dest.IsEqualInterior(RectType(rect1.x, rect1.y, rect1.width, rect1.height - 1)))) << + "[5] Test against a rect that overlaps the top edge of rect1"; + EXPECT_TRUE(dest.IsFinite()) << "[5b] Should be finite"; + rect2.y++; + + // Test against a rect that's outside of rect1 on the top + rect2.y -= rect2.height; + EXPECT_FALSE(dest.IntersectRect(rect1, rect2)) << + "[6] Test against a rect that's outside of rect1 on the top"; + // Make sure an empty rect is returned + EXPECT_FALSE(!dest.IsEmpty()) << + "[6] Make sure an empty rect is returned"; + EXPECT_TRUE(dest.IsFinite()) << "[6b] Should be finite"; + rect2.y += rect2.height; + + // Test against a rect that overlaps the right edge of rect1 + rect2.x++; + EXPECT_FALSE(!dest.IntersectRect(rect1, rect2) || + !(dest.IsEqualInterior(RectType(rect1.x + 1, rect1.y, rect1.width - 1, rect1.height)))) << + "[7] Test against a rect that overlaps the right edge of rect1"; + rect2.x--; + + // Test against a rect that's outside of rect1 on the right + rect2.x += rect2.width; + EXPECT_FALSE(dest.IntersectRect(rect1, rect2)) << + "[8] Test against a rect that's outside of rect1 on the right"; + // Make sure an empty rect is returned + EXPECT_FALSE(!dest.IsEmpty()) << + "[8] Make sure an empty rect is returned"; + EXPECT_TRUE(dest.IsFinite()) << "[8b] Should be finite"; + rect2.x -= rect2.width; + + // Test against a rect that overlaps the bottom edge of rect1 + rect2.y++; + EXPECT_FALSE(!dest.IntersectRect(rect1, rect2) || + !(dest.IsEqualInterior(RectType(rect1.x, rect1.y + 1, rect1.width, rect1.height - 1)))) << + "[9] Test against a rect that overlaps the bottom edge of rect1"; + EXPECT_TRUE(dest.IsFinite()) << "[9b] Should be finite"; + rect2.y--; + + // Test against a rect that's outside of rect1 on the bottom + rect2.y += rect2.height; + EXPECT_FALSE(dest.IntersectRect(rect1, rect2)) << + "[10] Test against a rect that's outside of rect1 on the bottom"; + // Make sure an empty rect is returned + EXPECT_FALSE(!dest.IsEmpty()) << + "[10] Make sure an empty rect is returned"; + EXPECT_TRUE(dest.IsFinite()) << "[10b] Should be finite"; + rect2.y -= rect2.height; + + // Test against a rect with zero width or height + rect1.SetRect(100, 100, 100, 100); + rect2.SetRect(150, 100, 0, 100); + EXPECT_FALSE(dest.IntersectRect(rect1, rect2) || !dest.IsEmpty()) << + "[11] Intersection of rects with zero width or height should be empty"; + EXPECT_TRUE(dest.IsFinite()) << "[11b] Should be finite"; + + // Tests against a rect with negative width or height + // + + // Test against a rect with negative width + rect1.SetRect(100, 100, 100, 100); + rect2.SetRect(100, 100, -100, 100); + EXPECT_FALSE(dest.IntersectRect(rect1, rect2) || !dest.IsEmpty()) << + "[12] Intersection of rects with negative width or height should be empty"; + EXPECT_TRUE(dest.IsFinite()) << "[12b] Should be finite"; + + // Those two rects exactly overlap in some way... + // but we still want to return an empty rect + rect1.SetRect(100, 100, 100, 100); + rect2.SetRect(200, 200, -100, -100); + EXPECT_FALSE(dest.IntersectRect(rect1, rect2) || !dest.IsEmpty()) << + "[13] Intersection of rects with negative width or height should be empty"; + EXPECT_TRUE(dest.IsFinite()) << "[13b] Should be finite"; + + // Test against two identical rects with negative height + rect1.SetRect(100, 100, 100, -100); + rect2.SetRect(100, 100, 100, -100); + EXPECT_FALSE(dest.IntersectRect(rect1, rect2) || !dest.IsEmpty()) << + "[14] Intersection of rects with negative width or height should be empty"; + EXPECT_TRUE(dest.IsFinite()) << "[14b] Should be finite"; + + return true; +} + +template <class RectType> +static bool +TestUnion() +{ + RectType rect1; + RectType rect2(10, 10, 50, 50); + RectType dest; + + // Check the case where the receiver is an empty rect + rect1.SetEmpty(); + dest.UnionRect(rect1, rect2); + EXPECT_FALSE(dest.IsEmpty() || !dest.IsEqualInterior(rect2)) << + "[1] Check the case where the receiver is an empty rect"; + EXPECT_TRUE(dest.IsFinite()) << "[1b] Should be finite"; + + // Check the case where the source rect is an empty rect + rect1 = rect2; + rect2.SetEmpty(); + dest.UnionRect(rect1, rect2); + EXPECT_FALSE(dest.IsEmpty() || !dest.IsEqualInterior(rect1)) << + "[2] Check the case where the source rect is an empty rect"; + EXPECT_TRUE(dest.IsFinite()) << "[2b] Should be finite"; + + // Test the case where both rects are empty + rect1.SetEmpty(); + rect2.SetEmpty(); + dest.UnionRect(rect1, rect2); + EXPECT_FALSE(!dest.IsEmpty()) << + "[3] Test the case where both rects are empty"; + EXPECT_TRUE(dest.IsFinite()) << "[3b] Should be finite"; + + // Test union case where the two rects don't overlap at all + rect1.SetRect(10, 10, 50, 50); + rect2.SetRect(100, 100, 50, 50); + dest.UnionRect(rect1, rect2); + EXPECT_FALSE(dest.IsEmpty() || + !(dest.IsEqualInterior(RectType(rect1.x, rect1.y, rect2.XMost() - rect1.x, rect2.YMost() - rect1.y)))) << + "[4] Test union case where the two rects don't overlap at all"; + EXPECT_TRUE(dest.IsFinite()) << "[4b] Should be finite"; + + // Test union case where the two rects overlap + rect1.SetRect(30, 30, 50, 50); + rect2.SetRect(10, 10, 50, 50); + dest.UnionRect(rect1, rect2); + EXPECT_FALSE(dest.IsEmpty() || + !(dest.IsEqualInterior(RectType(rect2.x, rect2.y, rect1.XMost() - rect2.x, rect1.YMost() - rect2.y)))) << + "[5] Test union case where the two rects overlap"; + EXPECT_TRUE(dest.IsFinite()) << "[5b] Should be finite"; + + return true; +} + +static bool +TestFiniteGfx() +{ + float posInf = std::numeric_limits<float>::infinity(); + float negInf = -std::numeric_limits<float>::infinity(); + float justNaN = std::numeric_limits<float>::quiet_NaN(); + + gfxFloat values[4] = {5.0, 10.0, 15.0, 20.0}; + + // Try the "non-finite" values for x, y, width, height, one at a time + for (int i=0; i<4; i+=1) { + values[i] = posInf; + gfxRect rectPosInf(values[0], values[1], values[2], values[3]); + EXPECT_FALSE(rectPosInf.IsFinite()) << "For +inf (" << values[0] << "," << values[1] << "," << values[2] << "," << values[3] << ")"; + + values[i] = negInf; + gfxRect rectNegInf(values[0], values[1], values[2], values[3]); + EXPECT_FALSE(rectNegInf.IsFinite()) << "For -inf (" << values[0] << "," << values[1] << "," << values[2] << "," << values[3] << ")"; + + values[i] = justNaN; + gfxRect rectNaN(values[0], values[1], values[2], values[3]); + EXPECT_FALSE(rectNaN.IsFinite()) << "For NaN (" << values[0] << "," << values[1] << "," << values[2] << "," << values[3] << ")"; + + // Reset to a finite value... + values[i] = 5.0*i; + } + + return true; +} + +// We want to test nsRect values that are still in range but where +// the implementation is at risk of overflowing +template <class RectType> +static bool +TestBug1135677() +{ + RectType rect1(1073741344, 1073741344, 1073756696, 1073819936); + RectType rect2(1073741820, 1073741820, 14400, 77640); + RectType dest; + + dest = rect1.Intersect(rect2); + + EXPECT_TRUE(dest.x == 1073741820 && dest.y == 1073741820 && + dest.width == 14400 && dest.height == 77640) << + "[1] Operation should not overflow internally."; + + return true; +} + +TEST(Gfx, nsRect) { + TestConstructors<nsRect>(); + TestEqualityOperator<nsRect>(); + TestContainment<nsRect>(); + TestIntersects<nsRect>(); + TestIntersection<nsRect>(); + TestUnion<nsRect>(); + TestBug1135677<nsRect>(); +} + +TEST(Gfx, nsIntRect) { + TestConstructors<nsIntRect>(); + TestEqualityOperator<nsIntRect>(); + TestContainment<nsIntRect>(); + TestIntersects<nsIntRect>(); + TestIntersection<nsIntRect>(); + TestUnion<nsIntRect>(); + TestBug1135677<nsIntRect>(); +} + +TEST(Gfx, gfxRect) { + TestConstructors<gfxRect>(); + // Skip TestEqualityOperator<gfxRect>(); as gfxRect::operator== is private + TestContainment<gfxRect>(); + TestIntersects<gfxRect>(); + TestIntersection<gfxRect>(); + TestUnion<gfxRect>(); + TestBug1135677<gfxRect>(); + TestFiniteGfx(); +} |