office-rs 0.1.1

A Rust library for reading and writing XML Office files
Documentation
//! 基础算术运算公式测试
//! 测试加减乘除、幂运算、一元操作符等基础算术功能

use office_rs::error::Result;
use office_rs::xlsx::{
    CellProvider,
    CellReference,
    CellValue,
    FormulaCalculator,
    FormulaValue,
    parse_formula,
};
use std::collections::HashMap;

/// 简单的单元格提供者实现,用于测试
struct TestCellProvider {
    cells: HashMap<String, CellValue>,
}

impl TestCellProvider {
    fn new() -> Self {
        let mut cells = HashMap::new();

        // 设置测试数据
        cells.insert("A1".to_string(), CellValue::Number(10.0));
        cells.insert("A2".to_string(), CellValue::Number(5.0));
        cells.insert("A3".to_string(), CellValue::Number(2.0));
        cells.insert("B1".to_string(), CellValue::Number(3.0));
        cells.insert("B2".to_string(), CellValue::Number(0.0));
        cells.insert("C1".to_string(), CellValue::Text("Hello".to_string()));
        cells.insert("C2".to_string(), CellValue::Boolean(true));
        cells.insert("C3".to_string(), CellValue::Boolean(false));

        Self { cells }
    }
}

impl CellProvider for TestCellProvider {
    fn get_cell_value(&self, reference: &CellReference) -> Result<CellValue> {
        let key = reference.to_a1();
        Ok(self.cells.get(&key).cloned().unwrap_or(CellValue::Empty))
    }

    fn get_range_values(
        &self,
        _start: &CellReference,
        _end: &CellReference
    ) -> Result<Vec<Vec<CellValue>>> {
        // 简化实现,仅用于基础测试
        Ok(vec![])
    }
}

/// 测试加法运算
#[test]
fn test_addition() -> Result<()> {
    let provider = Box::new(TestCellProvider::new());
    let mut calculator = FormulaCalculator::new(provider);

    // 常量加法
    let expr = parse_formula("=1+2")?;
    let result = calculator.evaluate(&expr)?;
    assert_eq!(result, FormulaValue::Number(3.0));

    // 单元格加法
    let expr = parse_formula("=A1+A2")?;
    let result = calculator.evaluate(&expr)?;
    assert_eq!(result, FormulaValue::Number(15.0));

    // 混合加法
    let expr = parse_formula("=A1+5")?;
    let result = calculator.evaluate(&expr)?;
    assert_eq!(result, FormulaValue::Number(15.0));

    // 多项加法
    let expr = parse_formula("=A1+A2+A3")?;
    let result = calculator.evaluate(&expr)?;
    assert_eq!(result, FormulaValue::Number(17.0));

    // 负数加法
    let expr = parse_formula("=A1+(-A2)")?;
    let result = calculator.evaluate(&expr)?;
    assert_eq!(result, FormulaValue::Number(5.0));

    println!("加法运算测试通过");
    Ok(())
}

/// 测试减法运算
#[test]
fn test_subtraction() -> Result<()> {
    let provider = Box::new(TestCellProvider::new());
    let mut calculator = FormulaCalculator::new(provider);

    // 常量减法
    let expr = parse_formula("=5-2")?;
    let result = calculator.evaluate(&expr)?;
    assert_eq!(result, FormulaValue::Number(3.0));

    // 单元格减法
    let expr = parse_formula("=A1-A2")?;
    let result = calculator.evaluate(&expr)?;
    assert_eq!(result, FormulaValue::Number(5.0));

    // 混合减法
    let expr = parse_formula("=A1-3")?;
    let result = calculator.evaluate(&expr)?;
    assert_eq!(result, FormulaValue::Number(7.0));

    // 负数减法
    let expr = parse_formula("=A1-(-A2)")?;
    let result = calculator.evaluate(&expr)?;
    assert_eq!(result, FormulaValue::Number(15.0));

    println!("减法运算测试通过");
    Ok(())
}

/// 测试乘法运算
#[test]
fn test_multiplication() -> Result<()> {
    let provider = Box::new(TestCellProvider::new());
    let mut calculator = FormulaCalculator::new(provider);

    // 常量乘法
    let expr = parse_formula("=3*4")?;
    let result = calculator.evaluate(&expr)?;
    assert_eq!(result, FormulaValue::Number(12.0));

    // 单元格乘法
    let expr = parse_formula("=A1*A2")?;
    let result = calculator.evaluate(&expr)?;
    assert_eq!(result, FormulaValue::Number(50.0));

    // 混合乘法
    let expr = parse_formula("=A1*2")?;
    let result = calculator.evaluate(&expr)?;
    assert_eq!(result, FormulaValue::Number(20.0));

    // 多项乘法
    let expr = parse_formula("=A1*A2*A3")?;
    let result = calculator.evaluate(&expr)?;
    assert_eq!(result, FormulaValue::Number(100.0));

    println!("乘法运算测试通过");
    Ok(())
}

/// 测试除法运算
#[test]
fn test_division() -> Result<()> {
    let provider = Box::new(TestCellProvider::new());
    let mut calculator = FormulaCalculator::new(provider);

    // 常量除法
    let expr = parse_formula("=8/2")?;
    let result = calculator.evaluate(&expr)?;
    assert_eq!(result, FormulaValue::Number(4.0));

    // 单元格除法
    let expr = parse_formula("=A1/A3")?;
    let result = calculator.evaluate(&expr)?;
    assert_eq!(result, FormulaValue::Number(5.0));

    // 混合除法
    let expr = parse_formula("=A1/2")?;
    let result = calculator.evaluate(&expr)?;
    assert_eq!(result, FormulaValue::Number(5.0));

    // 除零错误
    let expr = parse_formula("=A1/B2")?; // B2是0
    let result = calculator.evaluate(&expr)?;
    assert_eq!(result, FormulaValue::Error(office_rs::xlsx::FormulaError::DivisionByZero));

    println!("除法运算测试通过");
    Ok(())
}

/// 测试幂运算
#[test]
fn test_power() -> Result<()> {
    let provider = Box::new(TestCellProvider::new());
    let mut calculator = FormulaCalculator::new(provider);

    // 常量幂运算
    let expr = parse_formula("=2^3")?;
    let result = calculator.evaluate(&expr)?;
    assert_eq!(result, FormulaValue::Number(8.0));

    // 单元格幂运算
    let expr = parse_formula("=A3^B1")?; // 2^3
    let result = calculator.evaluate(&expr)?;
    assert_eq!(result, FormulaValue::Number(8.0));

    // 混合幂运算
    let expr = parse_formula("=A3^2")?;
    let result = calculator.evaluate(&expr)?;
    assert_eq!(result, FormulaValue::Number(4.0));

    println!("幂运算测试通过");
    Ok(())
}

/// 测试一元操作符
#[test]
fn test_unary_operators() -> Result<()> {
    let provider = Box::new(TestCellProvider::new());
    let mut calculator = FormulaCalculator::new(provider);

    // 正号
    let expr = parse_formula("=+5")?;
    let result = calculator.evaluate(&expr)?;
    assert_eq!(result, FormulaValue::Number(5.0));

    // 负号
    let expr = parse_formula("=-5")?;
    let result = calculator.evaluate(&expr)?;
    assert_eq!(result, FormulaValue::Number(-5.0));

    // 负号与单元格
    let expr = parse_formula("=-A1")?;
    let result = calculator.evaluate(&expr)?;
    assert_eq!(result, FormulaValue::Number(-10.0));

    // 百分号
    let expr = parse_formula("=50%")?;
    let result = calculator.evaluate(&expr)?;
    assert_eq!(result, FormulaValue::Number(0.5));

    // 百分号与单元格
    let expr = parse_formula("=A1%")?;
    let result = calculator.evaluate(&expr)?;
    assert_eq!(result, FormulaValue::Number(0.1));

    println!("一元操作符测试通过");
    Ok(())
}

/// 测试运算符优先级
#[test]
fn test_operator_precedence() -> Result<()> {
    let provider = Box::new(TestCellProvider::new());
    let mut calculator = FormulaCalculator::new(provider);

    // 乘法优先于加法
    let expr = parse_formula("=2+3*4")?;
    let result = calculator.evaluate(&expr)?;
    assert_eq!(result, FormulaValue::Number(14.0));

    // 括号优先
    let expr = parse_formula("=(2+3)*4")?;
    let result = calculator.evaluate(&expr)?;
    assert_eq!(result, FormulaValue::Number(20.0));

    // 幂运算右结合
    let expr = parse_formula("=2^3^2")?;
    let result = calculator.evaluate(&expr)?;
    assert_eq!(result, FormulaValue::Number(512.0)); // 2^(3^2) = 2^9 = 512

    // 复杂表达式
    let expr = parse_formula("=A1+A2*A3-B1")?; // 10+5*2-3 = 10+10-3 = 17
    let result = calculator.evaluate(&expr)?;
    assert_eq!(result, FormulaValue::Number(17.0));

    // 复杂不含括号表达式
    let expr = parse_formula("=2+3*4^2%")?; // 2+3*4^2% = 2+(3*(4^(2%))) = 2+(3*(4^(2%))) = 5.0843414799682
    let result = calculator.evaluate(&expr)?;
    assert_eq!(result, FormulaValue::Number(5.0843414799682));

    // 复杂含括号表达式
    let expr = parse_formula("=2+((3*4)^2)%")?; // 2+((3*4)^2)% = 3.44
    let result = calculator.evaluate(&expr)?;
    assert_eq!(result, FormulaValue::Number(3.44));

    println!("运算符优先级测试通过");
    Ok(())
}

/// 测试类型转换
#[test]
fn test_type_conversions() -> Result<()> {
    let provider = Box::new(TestCellProvider::new());
    let mut calculator = FormulaCalculator::new(provider);

    // 布尔值转数字
    let expr = parse_formula("=C2+C3")?; // true + false = 1 + 0 = 1
    let result = calculator.evaluate(&expr)?;
    assert_eq!(result, FormulaValue::Number(1.0));

    // 文本转数字(如果可能)
    let expr = parse_formula("=A1+\"5\"")?;
    let result = calculator.evaluate(&expr)?;
    assert_eq!(result, FormulaValue::Number(15.0));

    // 无法转换的文本
    let expr = parse_formula("=A1+\"abc\"")?;
    let result = calculator.evaluate(&expr);
    assert!(result.is_err());

    println!("类型转换测试通过");
    Ok(())
}

/// 测试错误处理
#[test]
fn test_error_handling() -> Result<()> {
    let provider = Box::new(TestCellProvider::new());
    let mut calculator = FormulaCalculator::new(provider);

    // 除零错误
    let expr = parse_formula("=1/0")?;
    let result = calculator.evaluate(&expr)?;
    assert_eq!(result, FormulaValue::Error(office_rs::xlsx::FormulaError::DivisionByZero));

    // 无效的文本转换
    let expr = parse_formula("=\"abc\"+5")?;
    let result = calculator.evaluate(&expr);
    assert!(result.is_err());

    println!("错误处理测试通过");
    Ok(())
}

#[test]
fn test_multi_operators() -> Result<()> {
    let provider = Box::new(TestCellProvider::new());
    let mut calculator = FormulaCalculator::new(provider);

    // 常量乘法
    let expr = parse_formula("=3*-4")?;
    let result = calculator.evaluate(&expr)?;
    assert_eq!(result, FormulaValue::Number(-12.0));

    // 单元格乘法
    let expr = parse_formula("=A1*-A2")?;
    let result = calculator.evaluate(&expr)?;
    assert_eq!(result, FormulaValue::Number(-50.0));

    // 混合乘法
    let expr = parse_formula("=-A1*2")?;
    let result = calculator.evaluate(&expr)?;
    assert_eq!(result, FormulaValue::Number(-20.0));

    // 多项乘法
    let expr = parse_formula("=A1*-A2*A3")?;
    let result = calculator.evaluate(&expr)?;
    assert_eq!(result, FormulaValue::Number(-100.0));

    //
    let expr = parse_formula("=A1++A2")?;
    let result = calculator.evaluate(&expr)?;
    assert_eq!(result, FormulaValue::Number(15.0));

    // 多项乘法
    let expr = parse_formula("=A1--A2")?;
    let result = calculator.evaluate(&expr)?;
    assert_eq!(result, FormulaValue::Number(15.0));

    println!("乘法运算测试通过");
    Ok(())
}

/// 运行所有测试
fn main() -> Result<()> {
    test_addition()?;
    test_subtraction()?;
    test_multiplication()?;
    test_division()?;
    test_power()?;
    test_unary_operators()?;
    test_operator_precedence()?;
    test_type_conversions()?;
    test_error_handling()?;

    println!("所有基础算术运算测试通过!");
    Ok(())
}