123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264 |
- namespace Terminal.Gui.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);
- }
- }
|