Files
Terminal.Gui/Tests/UnitTestsParallelizable/Drawing/Region/SubtractRectangleTests.cs
Tig fdeaa8331b Fixes #4298 - Updates test namespaces (#4299)
* Refactored test namespaces.
Moved some tests that were in wrong project.
Code cleanup

* Parrallel -> Parallel
2025-10-20 14:14:38 -06:00

264 lines
10 KiB
C#

namespace UnitTests_Parallelizable.DrawingTests;
using Xunit;
public class SubtractRectangleTests
{
[Fact]
public void SubtractRectangle_NoOverlap_ReturnsOriginalRectangle ()
{
// Arrange: Non-overlapping rectangles
Rectangle original = new (0, 0, 10, 10);
Rectangle subtract = new (15, 15, 5, 5);
// Act: Subtract non-overlapping rectangle
var result = Region.SubtractRectangle (original, subtract).ToList ();
// Assert: Original rectangle unchanged
Assert.Single (result);
Assert.Equal (new Rectangle (0, 0, 10, 10), result [0]);
}
[Fact]
public void SubtractRectangle_CompleteOverlap_ReturnsEmpty ()
{
// Arrange: Subtract rectangle completely overlaps original
Rectangle original = new (0, 0, 5, 5);
Rectangle subtract = new (0, 0, 5, 5);
// Act: Subtract overlapping rectangle
var result = Region.SubtractRectangle (original, subtract).ToList ();
// Assert: No rectangles returned (empty result)
Assert.Empty (result);
}
[Fact]
public void SubtractRectangle_PartialOverlap_TopAndBottom ()
{
// Arrange: Original rectangle with subtract overlapping top and bottom
Rectangle original = new (0, 0, 10, 10);
Rectangle subtract = new (0, 4, 10, 2); // Overlaps y=4 to y=5
// Act: Subtract overlapping rectangle
var result = Region.SubtractRectangle (original, subtract).ToList ();
// Assert: Expect top (0,0,10,4) and bottom (0,6,10,4)
Assert.Equal (2, result.Count);
Assert.Contains (new Rectangle (0, 0, 10, 4), result); // Top part
Assert.Contains (new Rectangle (0, 6, 10, 4), result); // Bottom part
}
[Fact]
public void SubtractRectangle_PartialOverlap_LeftAndRight ()
{
// Arrange: Original rectangle with subtract overlapping left and right
Rectangle original = new (0, 0, 10, 10);
Rectangle subtract = new (4, 0, 2, 10); // Overlaps x=4 to x=5
// Act: Subtract overlapping rectangle
var result = Region.SubtractRectangle (original, subtract).ToList ();
// Assert: Expect left (0,0,4,10) and right (6,0,4,10)
Assert.Equal (2, result.Count);
Assert.Contains (new Rectangle (0, 0, 4, 10), result); // Left part
Assert.Contains (new Rectangle (6, 0, 4, 10), result); // Right part
}
[Fact]
public void SubtractRectangle_EmptyOriginal_ReturnsEmpty ()
{
// Arrange: Empty original rectangle
Rectangle original = Rectangle.Empty;
Rectangle subtract = new (0, 0, 5, 5);
// Act: Subtract from empty rectangle
var result = Region.SubtractRectangle (original, subtract).ToList ();
// Assert: No rectangles returned (empty result)
Assert.Empty (result);
}
[Fact]
public void SubtractRectangle_EmptySubtract_ReturnsOriginal ()
{
// Arrange: Empty subtract rectangle
Rectangle original = new (0, 0, 5, 5);
Rectangle subtract = Rectangle.Empty;
// Act: Subtract empty rectangle
var result = Region.SubtractRectangle (original, subtract).ToList ();
// Assert: Original rectangle unchanged
Assert.Single (result);
Assert.Equal (new Rectangle (0, 0, 5, 5), result [0]);
}
[Fact]
public void SubtractRectangle_ZeroWidthOrHeight_HandlesCorrectly ()
{
// Arrange: Rectangle with zero width or height
Rectangle original = new (0, 0, 5, 5);
Rectangle subtract = new (0, 0, 0, 5); // Zero width
// Act: Subtract zero-width rectangle
var result = Region.SubtractRectangle (original, subtract).ToList ();
// Assert: Original rectangle unchanged
Assert.Single (result);
Assert.Equal (new Rectangle (0, 0, 5, 5), result [0]);
}
[Fact]
public void SubtractRectangle_NegativeCoordinates_HandlesCorrectly ()
{
// Arrange:
// Original rectangle: (-5,-5) with width 10 and height 10.
// Subtract rectangle: (-3,-3) with width 2 and height 2.
Rectangle original = new (-5, -5, 10, 10);
Rectangle subtract = new (-3, -3, 2, 2);
// Act:
var results = Region.SubtractRectangle (original, subtract).ToList ();
// Expected fragments based on our algorithm:
// Top: (-5,-5,10,2)
// Bottom: (-5,-1,10,6)
// Left: (-5,-3,2,2)
// Right: (-1,-3,6,2)
var expectedTop = new Rectangle (-5, -5, 10, 2);
var expectedBottom = new Rectangle (-5, -1, 10, 6);
var expectedLeft = new Rectangle (-5, -3, 2, 2);
var expectedRight = new Rectangle (-1, -3, 6, 2);
// Assert:
Assert.Contains (expectedTop, results);
Assert.Contains (expectedBottom, results);
Assert.Contains (expectedLeft, results);
Assert.Contains (expectedRight, results);
Assert.Equal (4, results.Count);
}
[Fact]
public void SubtractRectangle_EdgeOverlap_TopLeftCorner ()
{
// Arrange: Subtract overlaps only the top-left corner.
// Original: (0,0,5,5); Subtract: (0,0,1,1)
Rectangle original = new (0, 0, 5, 5);
Rectangle subtract = new (0, 0, 1, 1);
// Act:
var result = Region.SubtractRectangle (original, subtract).ToList ();
// The algorithm produces two fragments:
// 1. Bottom: (0,1,5,4)
// 2. Right: (1,0,4,1)
Assert.Equal (2, result.Count);
Assert.Contains (new Rectangle (0, 1, 5, 4), result);
Assert.Contains (new Rectangle (1, 0, 4, 1), result);
}
// Updated L-shaped test: The algorithm produces 6 fragments, not 5.
[Fact]
public void SubtractRectangle_LShapedSubtract_MultipleFragments ()
{
// Arrange:
// Original: (0,0,6,6)
// subtract1: (2,2,2,1) creates a horizontal gap.
// subtract2: (2,3,1,1) removes an additional piece from the bottom fragment.
Rectangle original = new (0, 0, 6, 6);
Rectangle subtract1 = new (2, 2, 2, 1);
Rectangle subtract2 = new (2, 3, 1, 1);
// Act:
var intermediateResult = Region.SubtractRectangle (original, subtract1).ToList ();
var finalResult = intermediateResult.SelectMany (r => Region.SubtractRectangle (r, subtract2)).ToList ();
// Explanation:
// After subtracting subtract1, we expect these 4 fragments:
// - Top: (0,0,6,2)
// - Bottom: (0,3,6,3)
// - Left: (0,2,2,1)
// - Right: (4,2,2,1)
// Then subtracting subtract2 from the bottom fragment (0,3,6,3) produces 3 fragments:
// - Bottom part: (0,4,6,2)
// - Left part: (0,3,2,1)
// - Right part: (3,3,3,1)
// Total fragments = 1 (top) + 3 (modified bottom) + 1 (left) + 1 (right) = 6.
Assert.Equal (6, finalResult.Count);
Assert.Contains (new Rectangle (0, 0, 6, 2), finalResult); // Top fragment remains unchanged.
Assert.Contains (new Rectangle (0, 4, 6, 2), finalResult); // Bottom part from modified bottom.
Assert.Contains (new Rectangle (0, 3, 2, 1), finalResult); // Left part from modified bottom.
Assert.Contains (new Rectangle (3, 3, 3, 1), finalResult); // Right part from modified bottom.
Assert.Contains (new Rectangle (0, 2, 2, 1), finalResult); // Left fragment from first subtraction.
Assert.Contains (new Rectangle (4, 2, 2, 1), finalResult); // Right fragment from first subtraction.
}
// Additional focused tests for L-shaped subtraction scenarios:
[Fact]
public void SubtractRectangle_LShapedSubtract_HorizontalThenVertical ()
{
// Arrange:
// First, subtract a horizontal band.
Rectangle original = new (0, 0, 10, 10);
Rectangle subtractHorizontal = new (0, 4, 10, 2);
var horizontalResult = Region.SubtractRectangle (original, subtractHorizontal).ToList ();
// Expect two fragments: top (0,0,10,4) and bottom (0,6,10,4).
Assert.Equal (2, horizontalResult.Count);
Assert.Contains (new Rectangle (0, 0, 10, 4), horizontalResult);
Assert.Contains (new Rectangle (0, 6, 10, 4), horizontalResult);
// Act:
// Now, subtract a vertical piece from the top fragment.
Rectangle subtractVertical = new (3, 0, 2, 4);
var finalResult = Region.SubtractRectangle (horizontalResult [0], subtractVertical).ToList ();
// Assert:
// The subtraction yields two fragments:
// Left fragment: (0,0,3,4)
// Right fragment: (5,0,5,4)
Assert.Equal (2, finalResult.Count);
Assert.Contains (new Rectangle (0, 0, 3, 4), finalResult);
Assert.Contains (new Rectangle (5, 0, 5, 4), finalResult);
}
[Fact]
public void SubtractRectangle_LShapedSubtract_VerticalThenHorizontal ()
{
// Arrange:
// First, subtract a vertical band.
// Original: (0,0,10,10)
// Vertical subtract: (4,0,2,10) produces two fragments:
// Left: (0,0,4,10) and Right: (6,0,4,10)
Rectangle original = new (0, 0, 10, 10);
Rectangle subtractVertical = new (4, 0, 2, 10);
var verticalResult = Region.SubtractRectangle (original, subtractVertical).ToList ();
Assert.Equal (2, verticalResult.Count);
Assert.Contains (new Rectangle (0, 0, 4, 10), verticalResult);
Assert.Contains (new Rectangle (6, 0, 4, 10), verticalResult);
// Act:
// Now, subtract a horizontal piece from the left fragment.
// Horizontal subtract: (0,3,4,2)
// from the left fragment (0,0,4,10)
// Let's determine the expected fragments:
// 1. Top band: since original.Top (0) < subtract.Top (3), we get:
// (0,0,4, 3) -- height = subtract.Top - original.Top = 3.
// 2. Bottom band: since original.Bottom (10) > subtract.Bottom (5), we get:
// (0,5,4, 5) -- height = original.Bottom - subtract.Bottom = 5.
// No left or right fragments are produced because subtractHorizontal spans the full width.
// Total fragments: 2.
Rectangle subtractHorizontal = new (0, 3, 4, 2);
var finalResult = Region.SubtractRectangle (verticalResult [0], subtractHorizontal).ToList ();
// Assert:
// Expecting two fragments: (0,0,4,3) and (0,5,4,5).
Assert.Equal (2, finalResult.Count);
Assert.Contains (new Rectangle (0, 0, 4, 3), finalResult);
Assert.Contains (new Rectangle (0, 5, 4, 5), finalResult);
}
}