revue 2.71.1

A Vue-style TUI framework for Rust with CSS styling
Documentation
//! Boundary condition tests for numeric operations
//!
//! Tests edge cases for u16 numeric values including:
//! - Zero values
//! - u16::MAX boundaries
//! - Overflow scenarios
//! - Arithmetic underflow/overflow

use revue::layout::Rect;
use revue::render::Buffer;
use revue::style::Color;
use revue::widget::traits::RenderContext;
use revue::widget::{HSplit, Positioned, Text, VSplit};

/// Test zero width/height in various widgets
mod zero_values {
    use super::*;

    #[test]
    fn test_buffer_with_zero_width() {
        let buffer = Buffer::new(0, 10);
        assert_eq!(buffer.width(), 0);
        assert_eq!(buffer.height(), 10);
    }

    #[test]
    fn test_buffer_with_zero_height() {
        let buffer = Buffer::new(10, 0);
        assert_eq!(buffer.width(), 10);
        assert_eq!(buffer.height(), 0);
    }

    #[test]
    fn test_buffer_with_both_zero() {
        let buffer = Buffer::new(0, 0);
        assert_eq!(buffer.width(), 0);
        assert_eq!(buffer.height(), 0);
    }

    #[test]
    fn test_rect_with_zero_dimensions() {
        let rect = Rect::new(0, 0, 0, 0);
        assert_eq!(rect.width, 0);
        assert_eq!(rect.height, 0);
    }

    #[test]
    fn test_render_context_with_zero_area() {
        let mut buffer = Buffer::new(10, 10);
        let area = Rect::new(0, 0, 0, 0);
        let mut ctx = RenderContext::new(&mut buffer, area);

        // Should not panic with zero area
        ctx.draw_char(0, 0, 'x', Color::WHITE);
    }
}

/// Test u16::MAX boundary conditions
mod max_values {
    use super::*;

    #[test]
    fn test_buffer_with_max_width() {
        // Buffer has a security limit of MAX_BUFFER_DIMENSION (16,384)
        // instead of u16::MAX
        let buffer = Buffer::new(16_384, 10);
        assert_eq!(buffer.width(), 16_384);
    }

    #[test]
    fn test_buffer_with_max_height() {
        // Buffer has a security limit of MAX_BUFFER_DIMENSION (16,384)
        // instead of u16::MAX
        let buffer = Buffer::new(10, 16_384);
        assert_eq!(buffer.height(), 16_384);
    }

    #[test]
    fn test_rect_with_max_width() {
        let rect = Rect::new(0, 0, u16::MAX, 10);
        assert_eq!(rect.width, u16::MAX);
    }

    #[test]
    fn test_rect_with_max_height() {
        let rect = Rect::new(0, 0, 10, u16::MAX);
        assert_eq!(rect.height, u16::MAX);
    }
}

/// Test overflow scenarios
mod overflow_tests {
    use super::*;

    #[test]
    fn test_rect_coordinates_near_max() {
        // Coordinates near u16::MAX
        let x = u16::MAX - 10;
        let y = u16::MAX - 10;
        let rect = Rect::new(x, y, 10, 10);

        assert_eq!(rect.x, x);
        assert_eq!(rect.y, y);
    }

    #[test]
    fn test_positioned_with_negative_coords() {
        // Should accept negative coords
        let _positioned = Positioned::new(Text::new("Test")).x(-10).y(-5);

        // Positioned was created with negative coords
    }

    #[test]
    fn test_positioned_at_max_coords() {
        // Should accept max coords
        let _positioned = Positioned::new(Text::new("Test"))
            .x(u16::MAX as i16)
            .y(u16::MAX as i16);

        // Positioned was created with max coords
    }
}

/// Test arithmetic boundary conditions
mod arithmetic_boundaries {
    use super::*;

    #[test]
    fn test_rect_area_calculation() {
        let rect = Rect::new(0, 0, 100, 50);
        // Area = 100 * 50 = 5000 (fits in u32)
        assert_eq!(rect.width as u32 * rect.height as u32, 5000);
    }

    #[test]
    fn test_rect_with_large_values() {
        let rect = Rect::new(0, 0, 30000, 20000);
        // Area = 600,000,000 (fits in u32, exceeds u16)
        let area = rect.width as u32 * rect.height as u32;
        assert_eq!(area, 600_000_000);
    }

    #[test]
    fn test_split_with_max_ratio() {
        let split = HSplit::new(0.9);
        assert!(split.ratio <= 0.9);
    }
}

/// Test percentage calculations at boundaries
mod percentage_boundaries {
    use super::*;

    #[test]
    fn test_positioned_percent_zero() {
        // Should accept zero percent
        let _positioned = Positioned::new(Text::new("Test"))
            .percent_x(0.0)
            .percent_y(0.0);

        // Positioned was created with zero percent
    }

    #[test]
    fn test_positioned_percent_hundred() {
        // Should accept 100% percent
        let _positioned = Positioned::new(Text::new("Test"))
            .percent_x(100.0)
            .percent_y(100.0);

        // Positioned was created with 100% percent
    }

    #[test]
    fn test_splitter_ratio_zero() {
        let split = HSplit::new(0.0);
        // Should clamp to minimum
        assert!(split.ratio >= 0.1);
    }

    #[test]
    fn test_splitter_ratio_one() {
        let split = HSplit::new(1.0);
        // Should clamp to maximum
        assert!(split.ratio <= 0.9);
    }

    #[test]
    fn test_vsplit_ratio_boundaries() {
        let split_min = VSplit::new(0.0);
        let split_max = VSplit::new(1.0);

        assert!(split_min.ratio >= 0.1);
        assert!(split_max.ratio <= 0.9);
    }
}

/// Test saturating arithmetic
mod saturating_arithmetic {
    use super::*;

    #[test]
    fn test_rect_saturating_add() {
        let rect = Rect::new(u16::MAX - 5, u16::MAX - 5, 10, 10);

        // Adding to x should saturate, not overflow
        let new_x = rect.x.saturating_add(100);
        assert_eq!(new_x, u16::MAX);
    }

    #[test]
    fn test_rect_saturating_sub() {
        let rect = Rect::new(5, 5, 10, 10);

        // Subtracting from x should saturate to 0
        let new_x = rect.x.saturating_sub(100);
        assert_eq!(new_x, 0);
    }

    #[test]
    fn test_width_saturating_sub() {
        let rect = Rect::new(0, 0, 10, 10);

        // Subtracting more than width should give 0
        let new_width = rect.width.saturating_sub(20);
        assert_eq!(new_width, 0);
    }
}