188 lines
5.0 KiB
Rust
188 lines
5.0 KiB
Rust
use rlox::common::base_value::{BaseValue, Number};
|
|||
|
|
|
||
|
|
#[test]
|
||
|
|
fn test_number_addition_with_type_promotion() {
|
||
|
|
// Test float + int -> both become F64
|
||
|
|
let float_num = Number::F64(3.5);
|
||
|
|
let int_num = Number::I32(2);
|
||
|
|
let result = float_num.add(int_num);
|
||
|
|
match result {
|
||
|
|
Number::F64(val) => assert_eq!(val, 5.5),
|
||
|
|
_ => panic!("Expected F64 result from float + int"),
|
||
|
|
}
|
||
|
|
|
||
|
|
// Test int + unsigned -> both become I64
|
||
|
|
let int_num = Number::I32(-5);
|
||
|
|
let unsigned_num = Number::U32(10);
|
||
|
|
let result = int_num.add(unsigned_num);
|
||
|
|
match result {
|
||
|
|
Number::I64(val) => assert_eq!(val, 5),
|
||
|
|
_ => panic!("Expected I64 result from int + unsigned"),
|
||
|
|
}
|
||
|
|
|
||
|
|
// Test float + unsigned -> both become F64
|
||
|
|
let float_num = Number::F32(2.5);
|
||
|
|
let unsigned_num = Number::U64(3);
|
||
|
|
let result = float_num.add(unsigned_num);
|
||
|
|
match result {
|
||
|
|
Number::F64(val) => assert_eq!(val, 5.5),
|
||
|
|
_ => panic!("Expected F64 result from float + unsigned"),
|
||
|
|
}
|
||
|
|
|
||
|
|
// Test unsigned + unsigned -> both stay U128
|
||
|
|
let unsigned1 = Number::U32(100);
|
||
|
|
let unsigned2 = Number::U64(200);
|
||
|
|
let result = unsigned1.add(unsigned2);
|
||
|
|
match result {
|
||
|
|
Number::U128(val) => assert_eq!(val, 300),
|
||
|
|
_ => panic!("Expected U128 result from unsigned + unsigned"),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn test_number_subtraction() {
|
||
|
|
let a = Number::F64(10.5);
|
||
|
|
let b = Number::I32(5);
|
||
|
|
let result = a.sub(b);
|
||
|
|
match result {
|
||
|
|
Number::F64(val) => assert_eq!(val, 5.5),
|
||
|
|
_ => panic!("Expected F64 result"),
|
||
|
|
}
|
||
|
|
|
||
|
|
let a = Number::I32(10);
|
||
|
|
let b = Number::U32(3);
|
||
|
|
let result = a.sub(b);
|
||
|
|
match result {
|
||
|
|
Number::I64(val) => assert_eq!(val, 7),
|
||
|
|
_ => panic!("Expected I64 result"),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn test_number_multiplication() {
|
||
|
|
let a = Number::F64(2.5);
|
||
|
|
let b = Number::I32(4);
|
||
|
|
let result = a.mul(b);
|
||
|
|
match result {
|
||
|
|
Number::F64(val) => assert_eq!(val, 10.0),
|
||
|
|
_ => panic!("Expected F64 result"),
|
||
|
|
}
|
||
|
|
|
||
|
|
let a = Number::U32(5);
|
||
|
|
let b = Number::U32(6);
|
||
|
|
let result = a.mul(b);
|
||
|
|
match result {
|
||
|
|
Number::U128(val) => assert_eq!(val, 30),
|
||
|
|
_ => panic!("Expected U128 result"),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn test_number_division() {
|
||
|
|
let a = Number::F64(10.0);
|
||
|
|
let b = Number::I32(4);
|
||
|
|
let result = a.div(b).unwrap();
|
||
|
|
match result {
|
||
|
|
Number::F64(val) => assert_eq!(val, 2.5),
|
||
|
|
_ => panic!("Expected F64 result"),
|
||
|
|
}
|
||
|
|
|
||
|
|
// Test division by zero
|
||
|
|
let a = Number::I32(10);
|
||
|
|
let b = Number::I32(0);
|
||
|
|
assert!(a.div(b).is_none());
|
||
|
|
|
||
|
|
let a = Number::F64(10.0);
|
||
|
|
let b = Number::F64(0.0);
|
||
|
|
assert!(a.div(b).is_none());
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn test_number_remainder() {
|
||
|
|
let a = Number::I32(10);
|
||
|
|
let b = Number::I32(3);
|
||
|
|
let result = a.rem(b).unwrap();
|
||
|
|
match result {
|
||
|
|
Number::I64(val) => assert_eq!(val, 1),
|
||
|
|
_ => panic!("Expected I64 result"),
|
||
|
|
}
|
||
|
|
|
||
|
|
let a = Number::F64(10.5);
|
||
|
|
let b = Number::F64(3.0);
|
||
|
|
let result = a.rem(b).unwrap();
|
||
|
|
match result {
|
||
|
|
Number::F64(val) => assert_eq!(val, 1.5),
|
||
|
|
_ => panic!("Expected F64 result"),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn test_number_negation() {
|
||
|
|
let num = Number::I32(5);
|
||
|
|
let result = num.neg();
|
||
|
|
match result {
|
||
|
|
Number::I32(val) => assert_eq!(val, -5),
|
||
|
|
_ => panic!("Expected I32 result"),
|
||
|
|
}
|
||
|
|
|
||
|
|
let num = Number::U32(5);
|
||
|
|
let result = num.neg();
|
||
|
|
match result {
|
||
|
|
Number::I64(val) => assert_eq!(val, -5),
|
||
|
|
_ => panic!("Expected I64 result for negated unsigned"),
|
||
|
|
}
|
||
|
|
|
||
|
|
let num = Number::F64(3.5);
|
||
|
|
let result = num.neg();
|
||
|
|
match result {
|
||
|
|
Number::F64(val) => assert_eq!(val, -3.5),
|
||
|
|
_ => panic!("Expected F64 result"),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn test_number_comparison() {
|
||
|
|
let a = Number::I32(5);
|
||
|
|
let b = Number::F64(5.0);
|
||
|
|
assert_eq!(a.partial_cmp(&b), Some(std::cmp::Ordering::Equal));
|
||
|
|
|
||
|
|
let a = Number::I32(5);
|
||
|
|
let b = Number::F64(6.0);
|
||
|
|
assert_eq!(a.partial_cmp(&b), Some(std::cmp::Ordering::Less));
|
||
|
|
|
||
|
|
let a = Number::U32(10);
|
||
|
|
let b = Number::I32(5);
|
||
|
|
assert_eq!(a.partial_cmp(&b), Some(std::cmp::Ordering::Greater));
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn test_baevalue_operations() {
|
||
|
|
// Test BaseValue addition
|
||
|
|
let a = BaseValue::Number(Number::I32(5));
|
||
|
|
let b = BaseValue::Number(Number::F64(3.5));
|
||
|
|
let result = (a + b).unwrap();
|
||
|
|
match result {
|
||
|
|
BaseValue::Number(Number::F64(val)) => assert_eq!(val, 8.5),
|
||
|
|
_ => panic!("Expected Number(F64) result"),
|
||
|
|
}
|
||
|
|
|
||
|
|
// Test string concatenation
|
||
|
|
let a = BaseValue::String("Hello ".to_string());
|
||
|
|
let b = BaseValue::String("World".to_string());
|
||
|
|
let result = (a + b).unwrap();
|
||
|
|
match result {
|
||
|
|
BaseValue::String(s) => assert_eq!(s, "Hello World"),
|
||
|
|
_ => panic!("Expected String result"),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn test_is_zero() {
|
||
|
|
assert!(Number::I32(0).is_zero());
|
||
|
|
assert!(Number::F64(0.0).is_zero());
|
||
|
|
assert!(Number::U32(0).is_zero());
|
||
|
|
assert!(!Number::I32(1).is_zero());
|
||
|
|
assert!(!Number::F64(0.1).is_zero());
|
||
|
|
assert!(!Number::U32(1).is_zero());
|
||
|
|
}
|