1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/tests/gtest/TestRect.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,429 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "gtest/gtest.h" 1.10 + 1.11 +#include "nsRect.h" 1.12 +#include "gfxRect.h" 1.13 +#ifdef XP_WIN 1.14 +#include <windows.h> 1.15 +#endif 1.16 + 1.17 +template <class RectType> 1.18 +static bool 1.19 +TestConstructors() 1.20 +{ 1.21 + // Create a rectangle 1.22 + RectType rect1(10, 20, 30, 40); 1.23 + 1.24 + // Make sure the rectangle was properly initialized 1.25 + EXPECT_TRUE(rect1.x == 10 && rect1.y == 20 && 1.26 + rect1.width == 30 && rect1.height == 40) << 1.27 + "[1] Make sure the rectangle was properly initialized with constructor"; 1.28 + 1.29 + // Create a second rect using the copy constructor 1.30 + RectType rect2(rect1); 1.31 + 1.32 + // Make sure the rectangle was properly initialized 1.33 + EXPECT_TRUE(rect2.x == rect1.x && rect2.y == rect2.y && 1.34 + rect2.width == rect2.width && rect2.height == rect2.height) << 1.35 + "[2] Make sure the rectangle was properly initialized with copy constructor"; 1.36 + 1.37 + 1.38 + EXPECT_TRUE(!rect1.IsEmpty() && rect1.IsFinite() && 1.39 + !rect2.IsEmpty() && rect2.IsFinite()) << 1.40 + "[3] These rectangles are not empty and are finite"; 1.41 + 1.42 + return true; 1.43 +} 1.44 + 1.45 +template <class RectType> 1.46 +static bool 1.47 +TestEqualityOperator() 1.48 +{ 1.49 + RectType rect1(10, 20, 30, 40); 1.50 + RectType rect2(rect1); 1.51 + 1.52 + // Test the equality operator 1.53 + EXPECT_TRUE(rect1 == rect2) << 1.54 + "[1] Test the equality operator"; 1.55 + 1.56 + EXPECT_FALSE(!rect1.IsEqualInterior(rect2)) << 1.57 + "[2] Test the inequality operator"; 1.58 + 1.59 + // Make sure that two empty rects are equal 1.60 + rect1.SetEmpty(); 1.61 + rect2.SetEmpty(); 1.62 + EXPECT_TRUE(rect1 == rect2) << 1.63 + "[3] Make sure that two empty rects are equal"; 1.64 + 1.65 + return true; 1.66 +} 1.67 + 1.68 +template <class RectType> 1.69 +static bool 1.70 +TestContainment() 1.71 +{ 1.72 + RectType rect1(10, 10, 50, 50); 1.73 + 1.74 + // Test the point containment methods 1.75 + // 1.76 + 1.77 + // Basic test of a point in the middle of the rect 1.78 + EXPECT_FALSE(!rect1.Contains(rect1.x + rect1.width/2, rect1.y + rect1.height/2)) << 1.79 + "[1] Basic test of a point in the middle of the rect"; 1.80 + 1.81 + // Test against a point at the left/top edges 1.82 + EXPECT_FALSE(!rect1.Contains(rect1.x, rect1.y)) << 1.83 + "[2] Test against a point at the left/top edges"; 1.84 + 1.85 + // Test against a point at the right/bottom extents 1.86 + EXPECT_FALSE(rect1.Contains(rect1.XMost(), rect1.YMost())) << 1.87 + "[3] Test against a point at the right/bottom extents"; 1.88 + 1.89 + // Test the rect containment methods 1.90 + // 1.91 + RectType rect2(rect1); 1.92 + 1.93 + // Test against a rect that's the same as rect1 1.94 + EXPECT_FALSE(!rect1.Contains(rect2)) << 1.95 + "[4] Test against a rect that's the same as rect1"; 1.96 + 1.97 + // Test against a rect whose left edge (only) is outside of rect1 1.98 + rect2.x--; 1.99 + EXPECT_FALSE(rect1.Contains(rect2)) << 1.100 + "[5] Test against a rect whose left edge (only) is outside of rect1"; 1.101 + rect2.x++; 1.102 + 1.103 + // Test against a rect whose top edge (only) is outside of rect1 1.104 + rect2.y--; 1.105 + EXPECT_FALSE(rect1.Contains(rect2)) << 1.106 + "[6] Test against a rect whose top edge (only) is outside of rect1"; 1.107 + rect2.y++; 1.108 + 1.109 + // Test against a rect whose right edge (only) is outside of rect1 1.110 + rect2.x++; 1.111 + EXPECT_FALSE(rect1.Contains(rect2)) << 1.112 + "[7] Test against a rect whose right edge (only) is outside of rect1"; 1.113 + rect2.x--; 1.114 + 1.115 + // Test against a rect whose bottom edge (only) is outside of rect1 1.116 + rect2.y++; 1.117 + EXPECT_FALSE(rect1.Contains(rect2)) << 1.118 + "[8] Test against a rect whose bottom edge (only) is outside of rect1"; 1.119 + rect2.y--; 1.120 + 1.121 + return true; 1.122 +} 1.123 + 1.124 +// Test the method that returns a boolean result but doesn't return a 1.125 +// a rectangle 1.126 +template <class RectType> 1.127 +static bool 1.128 +TestIntersects() 1.129 +{ 1.130 + RectType rect1(10, 10, 50, 50); 1.131 + RectType rect2(rect1); 1.132 + 1.133 + // Test against a rect that's the same as rect1 1.134 + EXPECT_FALSE(!rect1.Intersects(rect2)) << 1.135 + "[1] Test against a rect that's the same as rect1"; 1.136 + 1.137 + // Test against a rect that's enclosed by rect1 1.138 + rect2.Inflate(-1, -1); 1.139 + EXPECT_FALSE(!rect1.Contains(rect2) || !rect1.Intersects(rect2)) << 1.140 + "[2] Test against a rect that's enclosed by rect1"; 1.141 + rect2.Inflate(1, 1); 1.142 + 1.143 + // Make sure inflate and deflate worked correctly 1.144 + EXPECT_TRUE(rect1.IsEqualInterior(rect2)) << 1.145 + "[3] Make sure inflate and deflate worked correctly"; 1.146 + 1.147 + // Test against a rect that overlaps the left edge of rect1 1.148 + rect2.x--; 1.149 + EXPECT_FALSE(!rect1.Intersects(rect2)) << 1.150 + "[4] Test against a rect that overlaps the left edge of rect1"; 1.151 + rect2.x++; 1.152 + 1.153 + // Test against a rect that's outside of rect1 on the left 1.154 + rect2.x -= rect2.width; 1.155 + EXPECT_FALSE(rect1.Intersects(rect2)) << 1.156 + "[5] Test against a rect that's outside of rect1 on the left"; 1.157 + rect2.x += rect2.width; 1.158 + 1.159 + // Test against a rect that overlaps the top edge of rect1 1.160 + rect2.y--; 1.161 + EXPECT_FALSE(!rect1.Intersects(rect2)) << 1.162 + "[6] Test against a rect that overlaps the top edge of rect1"; 1.163 + rect2.y++; 1.164 + 1.165 + // Test against a rect that's outside of rect1 on the top 1.166 + rect2.y -= rect2.height; 1.167 + EXPECT_FALSE(rect1.Intersects(rect2)) << 1.168 + "[7] Test against a rect that's outside of rect1 on the top"; 1.169 + rect2.y += rect2.height; 1.170 + 1.171 + // Test against a rect that overlaps the right edge of rect1 1.172 + rect2.x++; 1.173 + EXPECT_FALSE(!rect1.Intersects(rect2)) << 1.174 + "[8] Test against a rect that overlaps the right edge of rect1"; 1.175 + rect2.x--; 1.176 + 1.177 + // Test against a rect that's outside of rect1 on the right 1.178 + rect2.x += rect2.width; 1.179 + EXPECT_FALSE(rect1.Intersects(rect2)) << 1.180 + "[9] Test against a rect that's outside of rect1 on the right"; 1.181 + rect2.x -= rect2.width; 1.182 + 1.183 + // Test against a rect that overlaps the bottom edge of rect1 1.184 + rect2.y++; 1.185 + EXPECT_FALSE(!rect1.Intersects(rect2)) << 1.186 + "[10] Test against a rect that overlaps the bottom edge of rect1"; 1.187 + rect2.y--; 1.188 + 1.189 + // Test against a rect that's outside of rect1 on the bottom 1.190 + rect2.y += rect2.height; 1.191 + EXPECT_FALSE(rect1.Intersects(rect2)) << 1.192 + "[11] Test against a rect that's outside of rect1 on the bottom"; 1.193 + rect2.y -= rect2.height; 1.194 + 1.195 + return true; 1.196 +} 1.197 + 1.198 +// Test the method that returns a boolean result and an intersection rect 1.199 +template <class RectType> 1.200 +static bool 1.201 +TestIntersection() 1.202 +{ 1.203 + RectType rect1(10, 10, 50, 50); 1.204 + RectType rect2(rect1); 1.205 + RectType dest; 1.206 + 1.207 + // Test against a rect that's the same as rect1 1.208 + EXPECT_FALSE(!dest.IntersectRect(rect1, rect2) || !(dest.IsEqualInterior(rect1))) << 1.209 + "[1] Test against a rect that's the same as rect1"; 1.210 + 1.211 + // Test against a rect that's enclosed by rect1 1.212 + rect2.Inflate(-1, -1); 1.213 + EXPECT_FALSE(!dest.IntersectRect(rect1, rect2) || !(dest.IsEqualInterior(rect2))) << 1.214 + "[2] Test against a rect that's enclosed by rect1"; 1.215 + rect2.Inflate(1, 1); 1.216 + 1.217 + // Test against a rect that overlaps the left edge of rect1 1.218 + rect2.x--; 1.219 + EXPECT_FALSE(!dest.IntersectRect(rect1, rect2) || 1.220 + !(dest.IsEqualInterior(RectType(rect1.x, rect1.y, rect1.width - 1, rect1.height)))) << 1.221 + "[3] Test against a rect that overlaps the left edge of rect1"; 1.222 + rect2.x++; 1.223 + 1.224 + // Test against a rect that's outside of rect1 on the left 1.225 + rect2.x -= rect2.width; 1.226 + EXPECT_FALSE(dest.IntersectRect(rect1, rect2)) << 1.227 + "[4] Test against a rect that's outside of rect1 on the left"; 1.228 + // Make sure an empty rect is returned 1.229 + EXPECT_FALSE(!dest.IsEmpty()) << 1.230 + "[4] Make sure an empty rect is returned"; 1.231 + EXPECT_TRUE(dest.IsFinite()) << "[4b] Should be finite"; 1.232 + rect2.x += rect2.width; 1.233 + 1.234 + // Test against a rect that overlaps the top edge of rect1 1.235 + rect2.y--; 1.236 + EXPECT_FALSE(!dest.IntersectRect(rect1, rect2) || 1.237 + !(dest.IsEqualInterior(RectType(rect1.x, rect1.y, rect1.width, rect1.height - 1)))) << 1.238 + "[5] Test against a rect that overlaps the top edge of rect1"; 1.239 + EXPECT_TRUE(dest.IsFinite()) << "[5b] Should be finite"; 1.240 + rect2.y++; 1.241 + 1.242 + // Test against a rect that's outside of rect1 on the top 1.243 + rect2.y -= rect2.height; 1.244 + EXPECT_FALSE(dest.IntersectRect(rect1, rect2)) << 1.245 + "[6] Test against a rect that's outside of rect1 on the top"; 1.246 + // Make sure an empty rect is returned 1.247 + EXPECT_FALSE(!dest.IsEmpty()) << 1.248 + "[6] Make sure an empty rect is returned"; 1.249 + EXPECT_TRUE(dest.IsFinite()) << "[6b] Should be finite"; 1.250 + rect2.y += rect2.height; 1.251 + 1.252 + // Test against a rect that overlaps the right edge of rect1 1.253 + rect2.x++; 1.254 + EXPECT_FALSE(!dest.IntersectRect(rect1, rect2) || 1.255 + !(dest.IsEqualInterior(RectType(rect1.x + 1, rect1.y, rect1.width - 1, rect1.height)))) << 1.256 + "[7] Test against a rect that overlaps the right edge of rect1"; 1.257 + rect2.x--; 1.258 + 1.259 + // Test against a rect that's outside of rect1 on the right 1.260 + rect2.x += rect2.width; 1.261 + EXPECT_FALSE(dest.IntersectRect(rect1, rect2)) << 1.262 + "[8] Test against a rect that's outside of rect1 on the right"; 1.263 + // Make sure an empty rect is returned 1.264 + EXPECT_FALSE(!dest.IsEmpty()) << 1.265 + "[8] Make sure an empty rect is returned"; 1.266 + EXPECT_TRUE(dest.IsFinite()) << "[8b] Should be finite"; 1.267 + rect2.x -= rect2.width; 1.268 + 1.269 + // Test against a rect that overlaps the bottom edge of rect1 1.270 + rect2.y++; 1.271 + EXPECT_FALSE(!dest.IntersectRect(rect1, rect2) || 1.272 + !(dest.IsEqualInterior(RectType(rect1.x, rect1.y + 1, rect1.width, rect1.height - 1)))) << 1.273 + "[9] Test against a rect that overlaps the bottom edge of rect1"; 1.274 + EXPECT_TRUE(dest.IsFinite()) << "[9b] Should be finite"; 1.275 + rect2.y--; 1.276 + 1.277 + // Test against a rect that's outside of rect1 on the bottom 1.278 + rect2.y += rect2.height; 1.279 + EXPECT_FALSE(dest.IntersectRect(rect1, rect2)) << 1.280 + "[10] Test against a rect that's outside of rect1 on the bottom"; 1.281 + // Make sure an empty rect is returned 1.282 + EXPECT_FALSE(!dest.IsEmpty()) << 1.283 + "[10] Make sure an empty rect is returned"; 1.284 + EXPECT_TRUE(dest.IsFinite()) << "[10b] Should be finite"; 1.285 + rect2.y -= rect2.height; 1.286 + 1.287 + // Test against a rect with zero width or height 1.288 + rect1.SetRect(100, 100, 100, 100); 1.289 + rect2.SetRect(150, 100, 0, 100); 1.290 + EXPECT_FALSE(dest.IntersectRect(rect1, rect2) || !dest.IsEmpty()) << 1.291 + "[11] Intersection of rects with zero width or height should be empty"; 1.292 + EXPECT_TRUE(dest.IsFinite()) << "[11b] Should be finite"; 1.293 + 1.294 + // Tests against a rect with negative width or height 1.295 + // 1.296 + 1.297 + // Test against a rect with negative width 1.298 + rect1.SetRect(100, 100, 100, 100); 1.299 + rect2.SetRect(100, 100, -100, 100); 1.300 + EXPECT_FALSE(dest.IntersectRect(rect1, rect2) || !dest.IsEmpty()) << 1.301 + "[12] Intersection of rects with negative width or height should be empty"; 1.302 + EXPECT_TRUE(dest.IsFinite()) << "[12b] Should be finite"; 1.303 + 1.304 + // Those two rects exactly overlap in some way... 1.305 + // but we still want to return an empty rect 1.306 + rect1.SetRect(100, 100, 100, 100); 1.307 + rect2.SetRect(200, 200, -100, -100); 1.308 + EXPECT_FALSE(dest.IntersectRect(rect1, rect2) || !dest.IsEmpty()) << 1.309 + "[13] Intersection of rects with negative width or height should be empty"; 1.310 + EXPECT_TRUE(dest.IsFinite()) << "[13b] Should be finite"; 1.311 + 1.312 + // Test against two identical rects with negative height 1.313 + rect1.SetRect(100, 100, 100, -100); 1.314 + rect2.SetRect(100, 100, 100, -100); 1.315 + EXPECT_FALSE(dest.IntersectRect(rect1, rect2) || !dest.IsEmpty()) << 1.316 + "[14] Intersection of rects with negative width or height should be empty"; 1.317 + EXPECT_TRUE(dest.IsFinite()) << "[14b] Should be finite"; 1.318 + 1.319 + return true; 1.320 +} 1.321 + 1.322 +template <class RectType> 1.323 +static bool 1.324 +TestUnion() 1.325 +{ 1.326 + RectType rect1; 1.327 + RectType rect2(10, 10, 50, 50); 1.328 + RectType dest; 1.329 + 1.330 + // Check the case where the receiver is an empty rect 1.331 + rect1.SetEmpty(); 1.332 + dest.UnionRect(rect1, rect2); 1.333 + EXPECT_FALSE(dest.IsEmpty() || !dest.IsEqualInterior(rect2)) << 1.334 + "[1] Check the case where the receiver is an empty rect"; 1.335 + EXPECT_TRUE(dest.IsFinite()) << "[1b] Should be finite"; 1.336 + 1.337 + // Check the case where the source rect is an empty rect 1.338 + rect1 = rect2; 1.339 + rect2.SetEmpty(); 1.340 + dest.UnionRect(rect1, rect2); 1.341 + EXPECT_FALSE(dest.IsEmpty() || !dest.IsEqualInterior(rect1)) << 1.342 + "[2] Check the case where the source rect is an empty rect"; 1.343 + EXPECT_TRUE(dest.IsFinite()) << "[2b] Should be finite"; 1.344 + 1.345 + // Test the case where both rects are empty 1.346 + rect1.SetEmpty(); 1.347 + rect2.SetEmpty(); 1.348 + dest.UnionRect(rect1, rect2); 1.349 + EXPECT_FALSE(!dest.IsEmpty()) << 1.350 + "[3] Test the case where both rects are empty"; 1.351 + EXPECT_TRUE(dest.IsFinite()) << "[3b] Should be finite"; 1.352 + 1.353 + // Test union case where the two rects don't overlap at all 1.354 + rect1.SetRect(10, 10, 50, 50); 1.355 + rect2.SetRect(100, 100, 50, 50); 1.356 + dest.UnionRect(rect1, rect2); 1.357 + EXPECT_FALSE(dest.IsEmpty() || 1.358 + !(dest.IsEqualInterior(RectType(rect1.x, rect1.y, rect2.XMost() - rect1.x, rect2.YMost() - rect1.y)))) << 1.359 + "[4] Test union case where the two rects don't overlap at all"; 1.360 + EXPECT_TRUE(dest.IsFinite()) << "[4b] Should be finite"; 1.361 + 1.362 + // Test union case where the two rects overlap 1.363 + rect1.SetRect(30, 30, 50, 50); 1.364 + rect2.SetRect(10, 10, 50, 50); 1.365 + dest.UnionRect(rect1, rect2); 1.366 + EXPECT_FALSE(dest.IsEmpty() || 1.367 + !(dest.IsEqualInterior(RectType(rect2.x, rect2.y, rect1.XMost() - rect2.x, rect1.YMost() - rect2.y)))) << 1.368 + "[5] Test union case where the two rects overlap"; 1.369 + EXPECT_TRUE(dest.IsFinite()) << "[5b] Should be finite"; 1.370 + 1.371 + return true; 1.372 +} 1.373 + 1.374 +static bool 1.375 +TestFiniteGfx() 1.376 +{ 1.377 + // Doesn't appear that __builtin_inf() and __builtin_nan() are available on 1.378 + // all compilers, so go the old fashioned way for inf and nan. 1.379 + float posInf = 1.0/0.0; 1.380 + float negInf = -1.0/0.0; 1.381 + float justNaN = 0.0/0.0; 1.382 + 1.383 + gfxFloat values[4] = {5.0, 10.0, 15.0, 20.0}; 1.384 + 1.385 + // Try the "non-finite" values for x, y, width, height, one at a time 1.386 + for (int i=0; i<4; i+=1) { 1.387 + values[i] = posInf; 1.388 + gfxRect rectPosInf(values[0], values[1], values[2], values[3]); 1.389 + EXPECT_FALSE(rectPosInf.IsFinite()) << "For +inf (" << values[0] << "," << values[1] << "," << values[2] << "," << values[3] << ")"; 1.390 + 1.391 + values[i] = negInf; 1.392 + gfxRect rectNegInf(values[0], values[1], values[2], values[3]); 1.393 + EXPECT_FALSE(rectNegInf.IsFinite()) << "For -inf (" << values[0] << "," << values[1] << "," << values[2] << "," << values[3] << ")"; 1.394 + 1.395 + values[i] = justNaN; 1.396 + gfxRect rectNaN(values[0], values[1], values[2], values[3]); 1.397 + EXPECT_FALSE(rectNaN.IsFinite()) << "For NaN (" << values[0] << "," << values[1] << "," << values[2] << "," << values[3] << ")"; 1.398 + 1.399 + // Reset to a finite value... 1.400 + values[i] = 5.0*i; 1.401 + } 1.402 + 1.403 + return true; 1.404 +} 1.405 + 1.406 +TEST(Gfx, nsRect) { 1.407 + TestConstructors<nsRect>(); 1.408 + TestEqualityOperator<nsRect>(); 1.409 + TestContainment<nsRect>(); 1.410 + TestIntersects<nsRect>(); 1.411 + TestIntersection<nsRect>(); 1.412 + TestUnion<nsRect>(); 1.413 +} 1.414 + 1.415 +TEST(Gfx, nsIntRect) { 1.416 + TestConstructors<nsIntRect>(); 1.417 + TestEqualityOperator<nsIntRect>(); 1.418 + TestContainment<nsIntRect>(); 1.419 + TestIntersects<nsIntRect>(); 1.420 + TestIntersection<nsIntRect>(); 1.421 + TestUnion<nsIntRect>(); 1.422 +} 1.423 + 1.424 +TEST(Gfx, gfxRect) { 1.425 + TestConstructors<gfxRect>(); 1.426 + // Skip TestEqualityOperator<gfxRect>(); as gfxRect::operator== is private 1.427 + TestContainment<gfxRect>(); 1.428 + TestIntersects<gfxRect>(); 1.429 + TestIntersection<gfxRect>(); 1.430 + TestUnion<gfxRect>(); 1.431 + TestFiniteGfx(); 1.432 +}